# 观察者模式

> 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，本质上都是观察者模式。

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://anjia1.gitbook.io/design/patterns/behavioral/observer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
