定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。其实就是订阅模式。
使用场景
- 事件多级触发场景;
- 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系;
- 跨系统的消息交换场景,如消息队列,事件总线的处理机制
- RxJava,EventBus,ListView的适配器
UML图
优点
- 观察者和被观察者之间是抽象耦合,应对业务变化
- 增强系统灵活性,可扩展性
缺点
- 程序中包含一个被观察者,多个观察者,开发,调试等内容会比较复杂。
- 耦合度太低(HAHAHAHA尴尬),例如eventbus中有时候可能找不到消息从哪里发到哪里,建议注释上写上消息来源和消息去处
- java中消息的通知默认执行是顺序执行,一个观察者卡顿,可能会影响整体的速率,(建议采用异步来解决)
例子
DevTechFrontier是一个技术网站,当上面的内容更新时,系统会发邮件给订阅了该网站更新的程序员
- 被观察者角色,内容更新时,所有的观察者(程序员)都会收到相应的通知
import java.util.Observable;
/**
* DevTechFrontier这个网站是被观察者角色,当它的内容更新时,所有的观察者(程序员)都会收到相应的通知
* Created by Niwa on 2017/7/26.
*/
public class DevTechFrontierObservable extends Observable {
public void postNewPublication(String content) {
setChanged();
notifyObservers(content);
}
}
- 程序员类,观察者,在update()里处理被观察者更新时发出来的内容
import java.util.Observable;
import java.util.Observer;
/**
* 具体观察者实现类
* 程序员是观察者
* Created by Niwa on 2017/7/26.
*/
public class Coder implements Observer {
private String name;
public Coder(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("Hi," + name + ",DevTechFrontier:" + arg);
}
@Override
public String toString() {
return "程序员名字:" + name;
}
}
- 测试类,注册被观察者和观察者,发布订阅信息,
/** 客户端类
* Created by Niwa on 2017/7/26.
*/
public class Client {
public static void main(String[] arg) {
//被观察者
DevTechFrontierObservable devTechFrontier = new DevTechFrontierObservable();
//观察者
Coder coder1 = new Coder("minminaya");
Coder coder2 = new Coder("孙悟空");
//注册观察者到可观察对象的观察者列表中(订阅)
devTechFrontier.addObserver(coder1);
devTechFrontier.addObserver(coder2);
//发布消息
devTechFrontier.postNewPublication("我们网站有新的技术分享");
}
}
结果:
Hi,孙悟空,DevTechFrontier:我们网站有新的技术分享
Hi,minminaya,DevTechFrontier:我们网站有新的技术分享
源代码:DesignPattern
参考:
《Android源码设计模式解析与实战读书》
各大佬博客
end