设计模式--观察者模式

发布时间 2023-08-15 22:03:48作者: 伊文小哥

简介

观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个 “观察” 该对象的其他对象。例如,Excel中的数据与折线图、饼状图、柱状图之间的关系


组成

  • 发布者(Publisher) 会向其他对象发送关注的事件。 事件会在发布者自身状态改变或执行特定行为后发生。 发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架
  • 订阅者(Subscriber)  接口声明了通知接口。 在绝大多数情况下, 该接口仅包含一个 update更新方法。 该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息
  • 具体订阅者(Concrete Subscribers) 可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合
  • 客户端(Client) 会分别创建发布者和订阅者对象, 然后为订阅者注册发布者更新


实现方式

声明观察者接口

该接口至少应声明一个 response 方法接收信息推送

public interface Observer {
    void response();
}

具体观察者实现

public class ConcreteObserver1 implements Observer{
    @Override
    public void response() {
        System.out.println("观察者1收到消息");
    }
}
public class ConcreteObserver2 implements Observer{
    @Override
    public void response() {
        System.out.println("观察者2收到消息");
    }
}

声明发布者抽象类

声明发布者抽象类并定义一些接口来在列表中添加和删除订阅对象

public abstract class Subject {

    List<Observer> observerList = new ArrayList<>();

    public void addObserver(Observer observer) {
        observerList.add(observer);
    }

    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }

    public abstract void notifyObserver();
}

创建具体发布者类

每次发布者发生了重要事件时都必须通知所有的订阅者

public class ConcreteSubject extends Subject{

    @Override
    public void notifyObserver() {
        System.out.println("内容发生改变,通知观察者");
        for (Observer observer : observerList) {
            observer.response();
        }
    }
}

客户端使用

public class Main {

    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        subject.addObserver(new ConcreteObserver1());
        subject.addObserver(new ConcreteObserver2());
        subject.notifyObserver();
    }
}

优势和缺点

优势

  • 符合开闭原则
  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系
  • 目标与观察者之间建立了一套触发机制

缺点

  • 订阅者的通知顺序是随机的
  • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率
  • 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用

使用场景

当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时,可使用观察者模式


Java中使用案例

  • java.util.Observer/java.util.Observable (极少在真实世界中使用)
  • java.util.EventListener的所有实现 (几乎广泛存在于 Swing 组件中)

识别方法: 该模式可以通过将对象存储在列表中的订阅方法, 和对于面向该列表中对象的更新方法的调用来识别