
十五、设计模式之观察者模式VS发布订阅模式
所属类型 | 定义 |
---|---|
行为型 | 观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。 |
能帮我们干什么?
主要解决什么问题?
主要解决的是 一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作
**何时使用:**一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
**如何解决:**使用面向对象技术,可以将这种依赖关系弱化。
优缺点
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
缺点:
-
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
-
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
-
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用的场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
- 注意事项:
- 1、JAVA 中已经有了对观察者模式的支持类。
- 2、避免循环引用。
- 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
角色
- 抽象主题(Subject):
它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。 - 具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。 - 抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。 - 具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
实现
关键代码: 在抽象类里有一个 ArrayList 存放观察者们。
观察模式
难度: ⭐️⭐️ ⭐️
样例代码
java/com/kongxiang/raindrop/dp/type/behavior/observer · master · 无难事者若执 / 23种设计模式 · GitCode
描述:
客户存取钱业务,发送短信通知到客户
- 短信中心(观察者)
- 银行 (主题)
抽象主题
/**
* 被观察者(主题)
*
*/
public abstract class Subject {
/**
* 维护观察者的列表
*/
protected List<Observer> observerList = new ArrayList<>();
/**
* 增加一个观察者
*/
public void register(Observer observer) {
observerList.add(observer);
}
/**
* 移除一个观察者
*/
public void remove(Observer observer) {
observerList.remove(observer);
}
/**
* 通知方法
*/
public void notifyAllObserver() {
observerList.forEach((o) -> o.update(this));
}
}
具体主题(银行)
public class SubjectImpl extends Subject {
/**
* 余额
*/
private int money;
public int getMoney() {
return money;
}
/**
* 存钱
*/
public void save(int money) {
this.money += money;
System.out.println("客户存了:" + money);
notifyAllObserver();
}
/**
* 取钱
*/
public void remove(int money) {
this.money -= money;
System.out.println("客户取了:" + money);
notifyAllObserver();
}
}
观察者(短信中心)
public interface Observer {
/**
* 主题变动,通知观察者的方法
*/
public void update(Subject subject);
}
public class PrintObserser implements Observer {
@Override
public void update(Subject subject) {
System.out.println("短信通知:账号余额:" + ((SubjectImpl) subject).getMoney());
}
}
办理业务代码
public static void main(String[] args) {
// 银行系统存取钱业务
SubjectImpl subject = new SubjectImpl();
// 短信中心
Observer observer = new PrintObserser();
System.out.println("--------- 银行增加 短信中心。。。");
subject.register(observer);
subject.save(1000);
subject.remove(50);
subject.save(100);
subject.remove(300);
System.out.println("--------- 银行移除短信中心。。。");
subject.remove(observer);
subject.remove(30);
subject.save(300);
}
--------- 银行增加 短信中心。。。
客户存了:1000
短信通知:账号余额:1000
客户取了:50
短信通知:账号余额:950
客户存了:100
短信通知:账号余额:1050
客户取了:300
短信通知:账号余额:750
--------- 银行移除短信中心。。。
客户取了:30
客户存了:300
与目标 VM 断开连接, 地址为: ''127.0.0.1:53887',传输: '套接字''
进程已结束,退出代码0
VS 发布订阅者模式
- 发布者和订阅者完全解耦
- 增加了一个经纪人(调度中心),处理发布和通知的操作。并管理发布者和订阅者列表。
总结
观察者模式可以帮我们当一个对象被修改时, 自动通知依赖它的对象。观察者模式属于行为型模式。
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。 ,