1 介绍
观察者模式,又叫做发布/订阅(publish/subscribe)模式,属于对象的行为模式。
1.1 什么是观察者模式
观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
1.2 解决什么样的问题
当一个对象的改变(名词)需要改变(动词)其他对象的时候。
观察者模式可以解决什么问题:
1、应该定义对象间一对多的依赖关系,而不使对象紧密耦合。(达到依赖关系,又不紧耦合)
2、应该确保一个对象改变时,无限制的依赖对象自动更新。
3、应该一个对象可以通知无限制的其他对象。
第2种情况,消息中间件就是实现之一,当一个生产者发送消息过来,无限制的消费者拿到消息自动更新自己。
第3中情况,发布-订阅推模式,微信公众号应该就是其中有代表性的,当有内容更新,主动通知订阅者。
2 原理
2.1 uml图
-
类图
image.png
观察者模式中的角色有:
-
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
-
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
-
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
-
时序图
image.png
2.2 代码示例
Subject代码示例
public interface Subject {
/**
* 增加订阅者
* @param observer
*/
void attach(Observer observer);
/**
* 删除订阅者
* @param observer
*/
void detach(Observer observer);
/**
* 通知订阅者更新消息
*/
void notify(String message);
}
ConcreteSubject代码示例
public class ConcreteSubject implements Subject {
private List<Observer> observers =new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notify(String message) {
for (Observer o: observers) {
o.update();
}
}
}
Observer代码示例
public interface Observer {
void update();
}
ConcreteObserver代码示例
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("I am notified!");
}
}
调用示例
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.attach(observer);
// 通知已经订阅的员工
subject.notify("boss is coming!");
}
运行结果
I am notified!
2.3 优缺点
-
优点
-
满足了当一个对象的改变需要改变其他对象这个条件的前提下,实现了松耦合。
-
符合开闭原则,继承抽象主题添加被观察者,继承抽象观察者添加观察者。
-
缺点
-
如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。
-
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
-
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
3 适用场景
- 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
- 事件多级触发场景。
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
4 总结
- 观察者模式定义了对象之间的一对多关系。
- Subject用一个共同的接口来更新观察者。
- 观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
可从被观察者处push或者pull数据,然而push的方式被认为更正确。 - 有多个观察者时,不可以依赖特定的通知次序。
参考书籍及文章
1.《Java与模式》,电子工业出版社,阎宏
2.《Head First 设计模式(中文版)》,中国电力出版社
- 《大话设计模式》,清华大学出版社,程杰 4. 《设计模式——可复用面向对象软件的基础》,机械工业出版社,Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides
- 《设计模式(五)观察者模式》,https://blog.csdn.net/itachi85/article/details/50773358
- 《观察者模式》,https://www.cnblogs.com/mingmingcome/p/10600576.html
网友评论