# JavaScript设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
# 单例模式
规定一个类只有一个实例,并且提供可全局访问点。全局对象是最简单的单例模式:
let obj = {
name: 'singleton',
getInstance: function() {}
}
1
2
3
4
2
3
4
但是这种容易污染全局变量,不推荐使用,一般是通过闭包或代理形式实现:
- 闭包,判断实例
let createSingleton = (function() {
let instance = null
return function(name) {
this.name = name
if (instance) return instance
return instance = this
}
})()
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 代理,将创建对象的操作和判断实例分开
let createSinleton = (function() {
let instance = null
return function(name) {
this.name = name
if (instance) return instance
return instance = new Singleton(name)
}
})()
let Singleton = function(name) {
this.name = name
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
使用例子:
let getSingleton = function (fn) {
var result;
return function () {
return result || (result = fn.apply(this, arguments)); // 确定this上下文并传递参数
}
}
let createAlertMessage = function (html) {
var div = document.createElement('div');
div.innerHTML = html;
div.style.display = 'none';
document.body.appendChild(div);
return div;
}
let createSingleAlertMessage = getSingleton(createAlertMessage);
document.getElementById('loginBtn').onclick = function () {
let alertMessage = createSingleAlertMessage('hello world');
alertMessage.style.display = 'block';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 观察者模式
一个被称作 被观察者 的对象,维护一组被称为观察者的对象,这些对象依赖于被观察者,被观察者自动将自身的状态的任何变化通知给它们。 当一个被观察者需要将一些变化通知给观察者的时候,它将采用广播的方式。
大概结构像这样:
EventObserver
│
├── subscribe: adds new observable events
│
├── unsubscribe: removes observable events
|
└── broadcast: executes all events with bound data
1
2
3
4
5
6
7
2
3
4
5
6
7
实现代码:
class EventObserver {
constructor() {
this.observers = [];
}
subscribe(fn) {
this.observers.push(fn);
}
unsubscribe(fn) {
this.observers = this.observers.filter((subscriber) => subscriber !== fn);
}
broadcast(data) {
this.observers.forEach((subscriber) => subscriber(data));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
使用例子:
// <input id="input" >
const Observer = new EventObserver();
Observer.subscribe((text) => {
console.log(text)
});
const input = document.getElementById('input');
input.addEventListener('keyup', () => Observer.broadcast(input.value));
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 发布-订阅模式
class Observal {
eventList = {};
subscribe (key, fn) {
if (!this.eventList[key]) {
this.eventList[key] = []
}
this.eventList[key].push(fn)
}
publish (...args) {
let key = Array.prototype.shift.call(args)
let fns = this.eventList[key]
if (!fns || fns.length === 0) {
return false
}
for (let i = 0; i < fns.length; i++) {
fns[i].apply(this, args)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
使用例子:
const Observer = new Observal();
function funa(d) {console.log('a',d)}
function funb(d) {console.log('b',d)}
function func(d) {console.log('a copy',d)}
Observer.subscribe('a', funa)
Observer.subscribe('a', func)
Observer.subscribe('b', funb)
Observer.publish('a','hello')
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10