前言
观察者模式,又叫作发布-订阅模式。一般的特点为对象间的关系为一对多,当一个对象被修改的时候,就会通知它依赖的对象
定义
定义对象间一种一对多的依赖关系,每当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新
结构图
角色拆解分析:
1.Subject:抽象主题(被观察者),抽象主题角色把所有的观察者对象(任意数量)保存在一个集合里。抽象主题提供一个接口,可以增加、删除观察者对象
2.ConcreteSubject:具体主题(被观察者)。该角色将有关状态存入具体观察者对象,在具体被观察者内部状态发生改变时,给所有注册过的观察者发送通知。
3.Observer:抽象观察者,是观察者的抽象类。它定义一个更新接口,在被观察者状态改变时,更新自己
4.ConcreteObserver:具体被观察者,实现Observer定义的接口,被观察者状态更改时更新自己
举栗实现
我加入了“刘皇叔”的星球,并和球友一起关注了他的微信公众号。每天只要公号有新的技术文发布,我们就能在手机微信收到通知。
1.Observer抽象观察者
定义更新方法
public interface Observer {
public void update(String message);
}
2.ConcreteObserver具体观察者
我和一大票群友就是这个具体观察者,实现了抽象观察者的更新方法
public class WechatUser implements Observer {
private String name;
public WechatUser(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.print(name+"-"+message);
}
}
3.Observer抽象被观察者
提供了增加、删除和通知更新3个方法
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
public void notify(String message);
}
4.ConcreteObserver具体被观察者
Android大牛刘望舒就是被观察者,他那存储有关注他的粉丝,实现了抽象方法
public class LiuWangShu implements Subject {
//关键代码,用来存放观察者们
private List<Observer> list = new ArrayList<>();
@Override
public void attach(Observer observer) {
list.add(observer);
}
@Override
public void detach(Observer observer) {
list.remove(observer);
}
@Override
public void notify(String message) {
for (Observer observer:list){
observer.update(message);
}
}
}
5.客户端调用
public class ObserverClient {
public static void main(String []args){
//被观察者
LiuWangShu liuWangShu = new LiuWangShu();
//首先创建几个刘望舒的粉丝
Wechat husky = new Wechat("husky");
Wechat labrador = new Wechat("labrador");
//订阅公号
liuWangShu.attach(husky);
liuWangShu.attach(labrador);
//通知更新
liuWangShu.notify("今天发文了...");
}
}
优缺点对比
优点:
1.观察者、被观察者之间抽象耦合,方便扩展
2.方便建立一套触发机制
缺点:
1.一个被观察者和若干个观察者,java消息通知是顺序执行的,一个观察者卡顿,后面的就gg了。兼顾开发、运行效率,一般采用异步方式
使用场景
1.存在关联行为的场景
2.事件多级触发
3.跨系统的消息交换场景,如消息队列、事件总线的处理机制