前言
从第一篇工厂模式开始,我会持续地更新每一种设计模式的内容,争取用通俗易懂的语言讲解和解释清楚。如果对你学习设计模式有帮助,请不要吝啬手中的赞~ 如果对文章内容有任何疑惑都可以在评论区提出和讨论~
本系列文章中的完整源码已上传 github 仓库,你可以在这里 github.com/FatMii/Desi...获取。
同样的,如果对你有帮助,请给我一个star~谢谢
设计模式合集链接:
Hello~大家好,前面三篇我们已经学习工厂模式
,单例模式
,责任链模式
,观察者模式
。本篇我们继续学习第四种设计模式:观察者模式
。
观察者模式是什么呢?想象一下,你是一个热心的邻居,总爱窥探你家对面的老王家
的动静。每当老王家
开派对,你就知道得装作无意走过,加入狂欢。这里,老王家
就是被观察者,而你,这个总爱"偶遇"的热心邻居,就是观察者。简单来说,观察者模式就是:一个对象变得有趣了,所有关注它的对象都会收到通知,并且自动更新自己的状态------"嘿,
老王家又开派对了!"
现在,让我们用一个日常生活中的例子来说明这一点:
假设你的微信里关注了"美食探索"
公众号。这里,"美食探索"
就是那个老王,也就是被观察者
,而你和其他几千个饥饿的粉丝就是观察者们
。这种关系,就是一对多的关系
:一个公众号,无数观众
。每当公众号推出新的烧烤技巧或者最新的美食攻略时,所有的粉丝(也就是观察者们)都会立刻收到推送
!
代码实现
javascript
// 应用场景:1.dom监听 2.降价商品
class Subject {
constructor() {
this.Observers = [];
}
add(observer) {
this.Observers.push(observer);
}
remove(observer) {
this.Observers = this.Observers.filter((item) => item !== observer);
}
notify() {
this.Observers.forEach((item) => {
item.update();
});
}
}
//定义观察者对象
class Observer {
constructor(name) {
this.name = name;
}
update() {
console.log(`my name is:${this.name}`);
}
}
let sub = new Subject();
let obs1 = new Observer("observer11");
let obs2 = new Observer("observer22");
sub.add(obs1);
sub.add(obs2);
sub.notify();
console.log("删除obs1后再次通知:")
sub.remove(obs1);
sub.notify();
// my name is:observer11
// my name is:observer22
// 删除obs1后再次通知:
// my name is:observer22
Subject 类(被观察者)
- 构造函数 :
Subject
类有一个构造函数,初始化一个空数组Observers
,用来存储所有观察者对象。 - add 方法 : 用于添加一个新的观察者对象到
Observers
数组中。 - remove 方法 : 用于从
Observers
数组中移除一个指定的观察者对象。这里使用filter
方法来创建一个不包含被移除观察者的新数组,从而实现删除功能。 - notify 方法 : 遍历
Observers
数组中的每个观察者,并调用他们的update
方法。这个方法在被观察者状态改变时被调用,用以通知所有观察者。
Observer 类(观察者)
- 构造函数 : 每个
Observer
对象在创建时接受一个name
参数,这个名称被存储在对象属性中,用于标识不同的观察者。 - update 方法 : 当被观察者调用
notify
方法时,update
被执行,输出一个包含观察者名称的消息。这里的update
方法可以根据实际需要进行更复杂的逻辑扩展。
优点
- 支持广播通信:观察者模式支持广播方式的通信,被观察者可以无差别地通知所有注册的观察者,无需关心观察者的具体实现,这有利于事件驱动的程序设计。
- 动态添加和删除观察者:在观察者模式中,可以随时增加和删除观察者,这使得系统更加灵活,并易于扩展和修改。
- 符合开闭原则:新的观察者可以很容易地添加进系统中,而不必修改主体(被观察者)的代码。系统可以在运行时通过添加和移除观察者来增强或修改功能,符合开闭原则。
缺点
-
可能导致效率问题:如果观察者数量很多,且更新操作频繁,每次状态变化都会导致所有的观察者被通知和更新,这可能会消耗大量的计算资源或处理时间,尤其是在大型系统中。
-
更新的无序性:观察者被通知的顺序可能是不确定的,尤其是在异步处理模型中。这可能会导致在状态更新和数据一致性上的问题,特别是当观察者对数据的一致性有严格要求时。