这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战
介绍
本期会向介绍一种极其常见行为型设计模式——观察者模式,如果有看过vue2源码的同学,它在实现响应式的时候,里面就用到了观察者模式。它与发布订阅的目的是完全一样,只是发布订阅会多一个调度中心来完成任务。
举个栗子,家里使用的是智能家居,可以通过语音控制他们,如果我们发出回家对他们发出一道指令,就说,都灯打开,收到指令的智能灯就会全部点亮。那么,这些智能灯就是观察者,观察的是我说的灯打开这个行为。
概念
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
实现
接下来,我们就实现一下,刚才聚的那个智能灯的栗子吧。
var Subject = (function(){
var _subject = function(){
this.state = false;
this.observes = [];
};
_subject.prototype.attach = function(observer){
if(observer instanceof Observer){
this.observes.push(observer);
}
}
_subject.prototype.setState = function(value){
this.state = value;
this.observes.forEach(function(observer){
observer.update();
})
}
return _subject;
})();
这里state就代表我们是否让等都打开的变量,observes将会存放要控制到的智能灯。当我们设置setState的时候,会遍历observes,向每个执行update方法来完成打开操作。
var Observer = (function(){
var _observer = function(name,action){
this.name = name;
this.action = "点亮"
}
_observer.prototype.update = function(){
console.log(this.name + ":" + this.action)
}
return _observer;
})();
这里我们做了一个对象类,刚才说的遍历update方法就在这里执行。接下来,我们先实例化几盏智能灯吧。
var subject = new Subject();
var observer1 = new Observer("智能灯A");
var observer2 = new Observer("智能灯B");
var observer3 = new Observer("普通灯C");
subject.attach(observer1);
subject.attach(observer2);
我们这里做了三盏灯,但是只有允许智能灯A和智能灯B才会观察到我们的行为,而普通灯C无法感知我的行为。
subject.setState(true);
我们把state变为true表示我们下达了灯打开指令,可以看到一下子智能灯A和智能灯B这样就都亮了。
结语
观察者模式主要是解决一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优点:
- 观察者和被观察者是抽象耦合的。
- 根据业务模式可以建立一套触发机制,方便事件的调度。
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。