> For the complete documentation index, see [llms.txt](https://anjia1.gitbook.io/design/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://anjia1.gitbook.io/design/patterns/behavioral/observer.md).

# 观察者模式

> 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，分发器-监听器

<table><thead><tr><th width="207">设计原则</th><th>观察者模式</th></tr></thead><tbody><tr><td>封装变化</td><td>变化的是：主题的状态、观察者的数目和类型</td></tr><tr><td>针对接口编程</td><td>主题和观察者都是用的接口<br>主题跟踪实现观察者接口的对象<br>观察者通过主题接口注册并被通知</td></tr><tr><td>优先使用组合</td><td>主题接口 has 观察者接口的列表</td></tr><tr><td>松耦合</td><td>主题 vs 观察者</td></tr></tbody></table>

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

<figure><img src="/files/bdKzFJCkJjc9RKrKsiRB" alt=""><figcaption><p>Subject 和 Observer</p></figcaption></figure>

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

|        | 进程内的                                       | 跨进程的 |
| ------ | ------------------------------------------ | ---- |
| 同步阻塞的  |                                            |      |
| 异步非阻塞的 | <ul><li>另起一个新线程</li><li>EventBus</li></ul> | 消息队列 |

```java
// 说明：实现方法各式各样，函数和类的命名等会根据业务场景的不同有很大的差别
// 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，本质上都是观察者模式。

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

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