设计模式 - 观察者模式(设计模式介绍系列)(六)

135 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情

观察者模式的概念

观察者模式可以理解为一种基于事件响应的设计模式。

举例来说某个场景,一个发出通知的角色和一个被通知的角色,对于获取通知这件事,有两种实现方式:

  1. 第一种是被动通知的方式:被通知者每隔一段时间询问通知者是否有新消息。
  2. 第二种方式是通知者主动通知:通知者是消息的来源,将被通知者注册到通知者中,当通知者有新消息之后就直接主动通知“被通知者”。

相当于,第一种方式是拉取,第二种方式是推送

因为现如今开发使用的语言大多数都是“面向对象”的,所以在面向对象开发过程中,我们要尽量面向抽象,而不是面向具体的对象。这样可以尽量避免代码耦合,对于日后的迭代或者升级都比较有好处。

针对上述的第一种“拉取”的实现方式,我们可以明显地看出,这种做法是十分消耗资源的。有时候没有新消息也会持续地对通知者进行访问。对于第二种开发模式,我们就可以将其抽象为一种新的设计模式:观察者模式

观察者模式类图

我们依旧延续之前的讲解方式,先给出设计模式的类图,然后结合具体场景,给出示例代码,以便更直观地进行学习。

类图:

image.png

在观察者模式中,我们称呼上述概念“通知者”为被观察者;称呼“被通知者”为观察者

对应到类图中,Observer 就是观察者,Subject 就是被观察者。所有观察者都实现了Observer,所有被观察者都实现了Subject

Subject 的成员变量是ObserverList,存储着已注册的观察者。当有新消息的时候,被观察者会将消息通知到列表中的所有观察者。在这里我们可以看到,被观察者的成员变量ObserverList 依赖的是Observer 接口,而不是具体的观察者,这样就可以做到观察者与被观察者的紧耦合。

代码示例

接下来我们使用具体的代码示例来说明观察者模式的使用。

我们模拟一个场景,全市有很多家4s 店,4s 店正常给消费者提供服务之前需要消费者提前预约,消费者在预约之后需要进行排队,排到之后,4s 店会通知消费者到店服务。

在上述场景中,4s 店就是“被观察者”,而消费者就是“观察者”。

我们来实现这个场景:

首先是观察者接口定义

public interface Observer {
  // 每个具体观察者收到消息后被触发的回调方法,
  // 具体观察者实现这个方法,做出不同的反应
  public void update();
}

具体的观察者

public class ConsumerXiaoHong implements Observer{
  @Override
  public void update() {
    System.out.println("小红收到通知");
  }
}
public class ConsumerXiaoMing implements Observer{
  @Override
  public void update() {
    System.out.println("小明收到通知");
  }
}

被观察者抽象类定义

public abstract class Subject {
  private List<Observer> observerList = new ArrayList<>();
  // 添加观察者到观察者列表中
  public void attachObserver(Observer observer) {
    observerList.add(observer);
  }
  // 从观察者列表中移除观察者
  public void detachObserver(Observer observer) {
    observerList.remove(observer);
  }
  // 通知观察者
  public void notifyObservers() {
    for (Observer observer : observerList) {
      observer.update();
    }
  }
}

具体被观察者

public class Chevrolet extends Subject{
  public void newMessage() {
    notifyObservers();
  }
}

调用

public static void main(String[] args) {
  Chevrolet chevrolet4S = new Chevrolet();

  ConsumerXiaoHong xiaoHong = new ConsumerXiaoHong();
  ConsumerXiaoMing xiaoMing = new ConsumerXiaoMing();

  chevrolet4S.attachObserver(xiaoHong);
  chevrolet4S.attachObserver(xiaoMing);

  chevrolet4S.newMessage();
}

输出结果

小红收到通知
小明收到通知

总结

观察者模式的讲解结合类图和代码示例应该很好理解。

在日常开发中这个模式也是比较经常使用到的一种设计模式,但是上述场景比较简单,我们依旧需要根据不同场景进行定制化,以达到实现业务需求的目的。