定义了对象之间 一对多 的依赖,令多个 观察者 对象 同时监听 某一个主题对象,当 主题对象 发生改变时,所有的 观察者 都会 收到通知 并更新;
适用场景:
- 关联行为场景,建立一套 触发机制;
优点:
- 抽象耦合:在 观察者 和 被观察者 之间,建立了一个 抽象的 耦合; 由于 耦合 是抽象的,可以很容易扩展 观察者 和 被观察者;
- 广播通信:观察者模式 支持 广播通信,类似于消息广播,如果需要接收消息,只需要注册一下即可;
缺点:
- 依赖过多:观察者 之间 细节依赖 过多,会增加 时间消耗 和 程序的复杂程度;
- 这里的 细节依赖 指的是 触发机制,触发链条;如果 观察者设置过多,每次触发都要花很长时间去处理通知;
- 循环调用:避免 循环调用,观察者 与 被观察者 之间 绝对不允许循环依赖,否则会触发二者之间的 循环调用,导致系统崩溃;
类图
代码
class Star {
constructor(name) {
this.name = name;
this.state = '';
this.observers = [];
}
getState() {
return this.state;
}
setState(state) {
this.state = state;
this.notifyAllObservers();
}
attach(observer) {
this.observers.push(observer);
}
notifyAllObservers() {
this.observers.forEach(observer => observer.update());
}
}
class Fan {
constructor(name, subject) {
this.name = name;
this.subject = subject;
this.subject.attach(this);
}
update() {
console.log(`${this.subject.name}有新的状态-${this.subject.getState()},${this.name}正在更新`);
}
}
let star = new Star('赵丽颖');
let fan1 = new Fan('张三', star);
let fan2 = new Fan('李四', star);
star.setState('结婚');
经典场景
事件绑定
<body>
<button id="btn">click</button>
</body>
<script>
let btn = document.getElementById('btn');
btn.addEventListener('click', () => { alert(1) });
btn.addEventListener('click', () => { alert(2) });
btn.addEventListener('click', () => { alert(3) });
</script>
Promise
class Promise {
constructor(fn) {
this.callbacks = [];
let resolve = () => {
this.callbacks.forEach(callback => callback())
};
fn(resolve);
}
then(callback) {
this.callbacks.push(callback);
}
// ......
}
let promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(100);
}, 1000);
});
promise.then(() => console.log(1));
promise.then(() => console.log(2));
events 自定义事件
class EventEmitter {
constructor() {
this._events = {};
}
// 注册事件
on(type, listener) {
let listeners = this._events[type];
if (listeners) {
listeners.push(listener);
} else {
this._events[type] = [listener];
}
}
// 触发事件
emit(type) {
let listeners = this._events[type];
let args = Array.from(arguments).slice(1);
listeners.forEach(listener => listener(...args));
}
}
module.exports = EventEmitter;
const EventEmitter = require('./events');
let subject = new EventEmitter();
subject.on('click', function (name) {
console.log(1, name);
});
subject.on('click', function (name) {
console.log(2, name);
});
subject.emit('click', 'zhangsan');
外观模式
上一篇