设计模式---观察者模式

观察者一般可以看做是第三者,比如在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了。再比如,拍卖会的时候,大家相互叫价,拍卖师会观察最高标价,然后通知给其它竞价者竞价,这就是一个观察者模式。
观察者模式又叫做 发布—订阅模式 ,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知和更新,观察者模式提供了一个订阅模型,其中对象订阅事件并在发生时得到通知,这种模式是事件驱动的编程基石,它有利益于良好的面向对象的设计

观察者模式(前端)

定义:对象间的一种一对多的依赖关系。

需求:当一个对象的状态发生变化时,所有依赖于他的对象都将得到通知。

优点:时间上的解耦,对象之间的解耦。

实现

指定好谁充当发布者;
给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数。
下面举个例子,比如我们给页面中的一个dom节点绑定一个事件,其实就可以看做是一种观察者模式:

1
2
3
4
document.body.addEventListener("click", function() { 
alert("Hello World")
},false )
document.body.click() //模拟用户点击

总结:在上面的例子中,需要监听用户点击 document.body 的动作,但是我们是没办法预知用户将在什么时候点击的,因此我们订阅了 document.body 的 click 事件,当 body 节点被点击时,body 节点便会向订阅者发布 “Hello World” 消息。

观察者模式(后端)

在这里插入图片描述
其中,Subject类是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象;Observer类是抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己;ConcreteSubject类是具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知;ConcreteObserver是具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Subject {

//观察者数组
private Vector<Observer> oVector = new Vector<>();

//增加一个观察者
public void addObserver(Observer observer) {
this.oVector.add(observer);
}

//删除一个观察者
public void deleteObserver(Observer observer) {
this.oVector.remove(observer);
}

//通知所有观察者
public void notifyObserver() {
for(Observer observer : this.oVector) {
observer.update();
}
}

}
1
2
3
4
1 public interface Observer {
2 //更新
3 public void update();
4 }
1
2
3
4
5
6
7
8
9
public class ConcreteSubject extends Subject {

//具体业务
public void doSomething() {
//...
super.notifyObserver();
}

}
1
2
3
4
5
6
7
8
public class ConcreteObserver implements Observer {

@Override
public void update() {
System.out.println("收到消息,进行处理");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {

public static void main(String[] args) {
//创建一个主题
ConcreteSubject subject = new ConcreteSubject();
//定义一个观察者
Observer observer = new ConcreteObserver();
//观察
subject.addObserver(observer);
//开始活动
subject.doSomething();
}
}

运行结果:

在这里插入图片描述

观察者模式的应用

1. 何时使用
一个对象状态改变,所有的依赖对象都将得到通知
  2. 方法
使用面向对象技术
  3. 优点
观察者和被观察者是抽象耦合的
建立了一套触发机制
  4. 缺点
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
如果观察者和观察目标间有循环依赖,可能导致系统崩溃
没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的
  5. 使用场景
关联行为场景
事件多级触发场景
跨系统的消息变换场景,如消息队列的处理机制
  6. 应用实例
手机丢了,委托别人给其他人发消息通知
通知老师/老板来了
拍卖,拍卖师观察最高标价,然后通知给其它竞价者竞价
在一个目录下建立一个文件,会同时通知目录管理器增加目录,并通知磁盘减少空间,文件是被观察者,目录管理器和磁盘管理器是观察者
猫叫了一声,吓着了老鼠,也惊到了主人,猫是被观察者,老鼠和人是观察者
  7. 注意事项
避免循环引用
如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式

参考: https://www.cnblogs.com/adamjwh/p/10913660.html

参考: https://developer.51cto.com/art/201904/594382.htm

-------------本文结束感谢您的阅读-------------