观察者模式

Observer Design Pattern

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

  1. 在对象之间定义一个一对多的依赖

    • 一个主题,带有状态、并控制状态

    • 多个观察者,使用这些状态

    • 观察者是主题的依赖者(主题是数据的唯一拥有者)

  2. 当一个对象改变状态的时候,它的所有依赖对象都会收到通知,并自动更新

观察者模式,让对象保持消息灵通。主题通过通用接口来更新观察者。

一般情况下,被依赖的对象叫主题(Subject),依赖的对象叫观察者(Observer)。称呼比较灵活,不过只要应用场景符合刚刚给出的定义,都可以看作观察者模式。

  • Subject-Observer,主题-观察者

  • Observable-Observer,被观察者-观察者

  • Publisher-Subscriber,发布者-订阅者

  • Producer-Consumer,生产者-消费者

  • EventEmitter-EventListener,事件触发者-事件监听者

  • Dispatcher-Listener,分发器-监听器

设计原则
观察者模式

封装变化

变化的是:主题的状态、观察者的数目和类型

针对接口编程

主题和观察者都是用的接口 主题跟踪实现观察者接口的对象 观察者通过主题接口注册并被通知

优先使用组合

主题接口 has 观察者接口的列表

松耦合

主题 vs 观察者

观察者模式有几种不同的实现方式,但大多数都围绕着包括 subject 和 observer 接口的类设计。

Subject 和 Observer

实际上,观察者模式是一个比较抽象的模式,根据不同的应用场景和需求,有完全不同的实现方式。

进程内的
跨进程的

同步阻塞的

异步非阻塞的

  • 另起一个新线程

  • EventBus

消息队列

// 说明:实现方法各式各样,函数和类的命名等会根据业务场景的不同有很大的差别
// eg. 最经典的一种实现方式
public interface Subject {
  void registerObserver(Observer observer);
  void removeObserver(Observer observer);
  void notifyObservers(Message message);
}

public interface Observer {
  void update(Message message);
}

public class ConcreteSubject implements Subject {
  private List<Observer> observers = new ArrayList<Observer>();

  @Override
  public void registerObserver(Observer observer) {
    observers.add(observer);
  }

  @Override
  public void removeObserver(Observer observer) {
    observers.remove(observer);
  }

  @Override
  public void notifyObservers(Message message) {
    for (Observer observer : observers) {
      observer.update(message);
    }
  }

}

public class ConcreteObserverOne implements Observer {
  @Override
  public void update(Message message) {
    //TODO: 获取消息通知,执行自己的逻辑...
    System.out.println("ConcreteObserverOne is notified.");
  }
}

public class ConcreteObserverTwo implements Observer {
  @Override
  public void update(Message message) {
    //TODO: 获取消息通知,执行自己的逻辑...
    System.out.println("ConcreteObserverTwo is notified.");
  }
}

public class Demo {
  public static void main(String[] args) {
    ConcreteSubject subject = new ConcreteSubject();
    subject.registerObserver(new ConcreteObserverOne());
    subject.registerObserver(new ConcreteObserverTwo());
    subject.notifyObservers(new Message());
  }
}

观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如邮件订阅、RSS Feeds,本质上都是观察者模式。

举个例子:用户注册成功之后,会给用户发放投资体验金、发放优惠券、给用户发送一封“欢迎注册成功”的站内信、给另一个系统发送信息等(注册成功之后需要执行的后续操作越来越多)。

再比如:添加和移除监听器,即添加和移除观察者。

Last updated