1.定义 观察者模式又被称为发布-订阅模式,属于行为型设计模式的一种,是非常常用的模式。它的定义如下: 定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。 2.简介 观察者模式中包含以下角色:
Subject:抽象被观察者(即抽象主题)。抽象观察者把所有观察者对象保存在一个集合,每个被观察者都有任意数量的观察者。抽象观察者提供一个接口,可以增加和删除观察者。ConcreteSubject:具体被观察者(具体主题)。具体被观察者实现了抽象观察者的接口,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知。Observer:抽象观察者,观察者的抽象类。它定义了一个更新接口,在收到被观察者(主题)发生改变的时候更新自己。ConcreteObserver:具体观察者。实现抽象观察者定义的更新接口,以便在被观察者发生改变的时候更新自己。很好理解,观察者模式实际上跟公众号类似:多个用户(即观察者)订阅了一个公众号(被观察者),公众号内部保存了订阅者的一个集合以及增加、删除订阅者和更新消息的方法。而用户则在公众号更新的时候会收到相应的消息。 3.简单的实现:
创建抽象被观察者: public interface Subject { /** * 添加订阅者 * * @param observer */ void attach(Observer observer); /** * 删除订阅者 * * @param observer */ void detach(Observer observer); /** * 更新,发布消息 * * @param message */ void notify(String message); } 创建抽象观察者 public interface Observer { /** * 更新消息接口 * @param msg */ void update(String msg); } 被观察者的实现 public class ConcreteSubject implements Subject { //用于保存观察者的列表 private List<Observer> observerList = new ArrayList<>(); @Override public void attach(Observer observer) {//添加观察者 observerList.add(observer); } @Override public void detach(Observer observer) {//移除观察者 observerList.remove(observer); } @Override public void notify(String message) {//发布更新 //被观察者发布更新的时候遍历观察者,调用其更新方法 for (Observer observer : observerList) { observer.update(message); } } } 具体观察者的实现 public class ConcreteObserver implements Observer { private String observerName; //构造方法用于区分不同观察者 public ConcreteObserver(String observerName) { this.observerName = observerName; } //当被观察者更新时,更新自身 @Override public void update(String msg) { System.out.println(observerName + "收到消息:" + msg); } } 简单使用及结果 ConcreteObserver user1 = new ConcreteObserver("user1"); ConcreteObserver user2 = new ConcreteObserver("user2"); ConcreteObserver user3 = new ConcreteObserver("user3"); ConcreteSubject subject = new ConcreteSubject(); subject.attach(user1); subject.attach(user2); subject.attach(user3); subject.notify("公众号更新了");输出结果: 可以看到,上述声明的三个user在subject更新的时候都收到了消息。 4.优点、缺点:
优点:观察者与被观察者之间抽象耦合,容易扩展。方便建立一套处罚机制。缺点:如果程序中包含多个观察者和被观察者不易管理、调试。另外,android中的消息通知是顺序执行的,如果一个观察者卡顿会影响到整体的执行。5.应用场景
当一个对象的改变需要通知其它对象改变时,而且它不知道具体有多少个对象有待改变时。当一个对象必须通知其它对象,而它又不能假定其它对象是谁时。跨系统的消息交换场景,如消息队列、事件总线的处理机制。