定义

观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)。在 GoF 的《设计模式》一书中,它的定义是这样的:

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

被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。其他命名方式如Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener等。

结构

主要角色:

  1. 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  2. 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  3. 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  4. 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

结构图:
观察者模式(Observer Pattern) - 图1

应用

基本用法

  1. public interface Subject {
  2. void registerObserver(Observer observer);
  3. void removeObserver(Observer observer);
  4. void notifyObservers(Message message);
  5. }
  6. public interface Observer {
  7. void update(Message message);
  8. }
  9. public class ConcreteSubject implements Subject {
  10. private List<Observer> observers = new ArrayList<Observer>();
  11. @Override
  12. public void registerObserver(Observer observer) {
  13. observers.add(observer);
  14. }
  15. @Override
  16. public void removeObserver(Observer observer) {
  17. observers.remove(observer);
  18. }
  19. @Override
  20. public void notifyObservers(Message message) {
  21. for (Observer observer : observers) {
  22. observer.update(message);
  23. }
  24. }
  25. }
  26. public class ConcreteObserverOne implements Observer {
  27. @Override
  28. public void update(Message message) {
  29. //TODO: 获取消息通知,执行自己的逻辑...
  30. System.out.println("ConcreteObserverOne is notified.");
  31. }
  32. }
  33. public class ConcreteObserverTwo implements Observer {
  34. @Override
  35. public void update(Message message) {
  36. //TODO: 获取消息通知,执行自己的逻辑...
  37. System.out.println("ConcreteObserverTwo is notified.");
  38. }
  39. }
  40. public class Demo {
  41. public static void main(String[] args) {
  42. ConcreteSubject subject = new ConcreteSubject();
  43. subject.registerObserver(new ConcreteObserverOne());
  44. subject.registerObserver(new ConcreteObserverTwo());
  45. subject.notifyObservers(new Message());
  46. }
  47. }

用户注册


public interface RegObserver {
  void handleRegSuccess(long userId);
}

public class RegPromotionObserver implements RegObserver {
  private PromotionService promotionService; // 依赖注入

  @Override
  public void handleRegSuccess(long userId) {
    promotionService.issueNewUserExperienceCash(userId);
  }
}

public class RegNotificationObserver implements RegObserver {
  private NotificationService notificationService;

  @Override
  public void handleRegSuccess(long userId) {
    notificationService.sendInboxMessage(userId, "Welcome...");
  }
}

public class UserController {
  private UserService userService; // 依赖注入
  private List<RegObserver> regObservers = new ArrayList<>();

  // 一次性设置好,之后也不可能动态的修改
  public void setRegObservers(List<RegObserver> observers) {
    regObservers.addAll(observers);
  }

  public Long register(String telephone, String password) {
    //省略输入参数的校验代码
    //省略userService.register()异常的try-catch代码
    long userId = userService.register(telephone, password);

    for (RegObserver observer : regObservers) {
      observer.handleRegSuccess(userId);
    }

    return userId;
  }
}

消息队列

消息队列本身就是一种观察者模式,优点是解耦彻底,缺点是需要额外引入消息队列系统。

Google EventBus

EventBus(同步执行)、AsyncEventBus(线程池异步执行)

优点

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
  2. 目标与观察者之间建立了一套触发机制。

    缺点

  3. 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。

  4. 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

    扩展