设计模式(15/23) - 观察者模式

40 阅读3分钟

观察者模式

1 概述

  • 观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并自动更新。
  • 观察者模式通常用于实现分布式事件处理系统,广泛应用于各种场景,例如GUI事件处理、订阅-发布系统等。

2 优缺点及应用场景

2.1 优点

  • 1)解耦:观察者模式实现了观察者和被观察者的解耦,使得两者可以独立变化。
  • 2)灵活性:可以在运行时动态添加或移除观察者,灵活应对变化。
  • 3)符合开闭原则:增加新的观察者时无需修改现有代码,符合开闭原则。

2.2 缺点

  • 1)可能导致内存泄漏:如果观察者没有正确移除,可能会导致内存泄漏。
  • 2)通知顺序不确定:多个观察者的通知顺序是无序的,可能导致不一致性。

2.3 应用场景

  • 1)事件驱动系统:需要处理事件并通知多个响应对象的场景,例如GUI事件处理、系统事件处理等。
  • 2)订阅-发布系统:需要一个对象的状态改变能够通知到多个对象的场景,例如消息订阅系统、实时更新系统等。
  • 3)模型-视图模式:在MVC架构中,视图需要实时更新模型的变化。

3 结构

  • 1)主题(Subject):主题维护了一组观察者,并提供了添加、删除观察者的方法。当主题的状态发生变化时,通知所有观察者。
  • 2)观察者(Observer):观察者定义了一个更新接口,用于接收主题的通知。
  • 3)具体主题(ConcreteSubject):具体主题实现了主题接口,并在状态变化时通知所有观察者。
  • 4)具体观察者(ConcreteObserver):具体观察者实现了更新接口,以便使自身状态与主题的状态保持一致。

4 实现

4.1 UML 类图

观察者模式.jpg

4.2 代码示例

// 创建 Subject 类
class Subject {

  private List<Observer> observers = new ArrayList<Observer>();
  private int state;

  public int getState() {
    return state;
  }

  public void setState(int state) {
    this.state = state;
    notifyAllObservers();
  }

  public void attach(Observer observer) {
    observers.add(observer);
  }

  public void notifyAllObservers() {
    for (Observer observer : observers) {
      observer.update();
    }
  }
}

// 创建 Observer 类
abstract class Observer {
  protected Subject subject;

  public abstract void update();
}

// 创建实体观察者类:二进制观察者
class BinaryObserver extends Observer {
  public BinaryObserver(Subject subject) {
    this.subject = subject;
    this.subject.attach(this);
  }

  @Override
  public void update() {
    System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
  }
}

// 创建实体观察者类:八进制观察者
class OctalObserver extends Observer {
  public OctalObserver(Subject subject) {
    this.subject = subject;
    this.subject.attach(this);
  }

  @Override
  public void update() {
    System.out.println("Octal String: " + Integer.toOctalString(subject.getState()));
  }
}

// 创建实体观察者类:十六进制观察者
class HexaObserver extends Observer {
  public HexaObserver(Subject subject) {
    this.subject = subject;
    this.subject.attach(this);
  }

  @Override
  public void update() {
    System.out.println("Hex String: " + Integer.toHexString(subject.getState()).toUpperCase());
  }
}

// 使用示例
public class ObserverPatternDemo {
  public static void main(String[] args) {
    // 使用 Subject 和实体观察者对象
    Subject subject = new Subject();

    new HexaObserver(subject);
    new OctalObserver(subject);
    new BinaryObserver(subject);

    System.out.println("First state change: 15");
    subject.setState(15);
    System.out.println("Second state change: 10");
    subject.setState(10);
  }
}
  • 执行程序,输出结果:
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

5 总结

  • 观察者模式通过定义一对多的依赖关系,实现了观察者和被观察者之间的解耦,使得多个观察者对象能够同时监听一个主题对象,并在主题对象发生变化时自动更新。观察者模式适用于事件驱动系统、订阅-发布系统以及模型-视图模式等场景。尽管观察者模式提高了系统的灵活性和可扩展性,但也可能导致内存泄漏和通知顺序不确定等问题。在实际应用中,需要根据具体需求权衡使用观察者模式的利弊。