Loading...

设计模式-观察者模式

前言

在 Java 开发中,设计模式是常用的一种编码方式,合理使用设计模式可以帮助开发人员更快地编写出高效、可靠和可维护的代码。本期继续撰写设计模式系列文章,总共 23 种设计模式将以一篇一篇文章讲解,代码笔记已开源至:Gitee点击跳转

在上一篇《Java设计模式(17)备忘录模式》文章中,我们介绍了备忘录模式。本文是这个系列的第十八篇章,我们将讲解一下观察者模式的实现方式、应用场景以及它的用途。

观察者模式

观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系。当一个对象的状态发生变化时,所有依赖它的对象都会收到通知并自动更新。

在观察者模式中,被观察的对象通常称为主题或被观察者(Subject),接收通知的对象称为观察者(Observer)。Subject 负责维护观察者列表,并在需要的时候统一通知所有观察者。

这种模式可以让被观察者和观察者之间保持低耦合。被观察者不需要关心观察者具体做了什么,只需要调用统一的通知方法即可。

使用场景

  • 需要一个对象状态变化后通知多个对象的场景,如用户订阅消息、系统通知、商品降价提醒
  • 需要实现事件监听机制的场景,如按钮点击事件、监听器回调
  • 需要解耦消息发布者和接收者的场景,如消息订阅、发布通知
  • 需要动态添加或移除通知对象的场景,如用户订阅和取消订阅

代码实现

以下是一个简单的示例。我们将创建一个被观察者对象 ConcreteSubject,并创建多个观察者 ConcreteObserver。当被观察者发送消息时,所有已注册的观察者都可以收到通知。

/**
观察者接口
@author Jensen
@date 2024-01-18
*/
public interface Observer {
 void update(String msg);
}

/**
被观察者接口
@author Jensen
@date 2024-01-18
*/
public interface Subject {
 void registerObserver(Observer observer);
 void removeObserver(Observer observer);
 void notifyObservers(String message);
}

public class ConcreteSubject implements Subject {
    private final List<Observer> observers = new ArrayList<>();
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        observers.forEach(observer -> observer.update(message));
    }
}

public class ConcreteObserver implements Observer {
    private String name;
    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String msg) {
        System.out.println(name + " 收到的消息是:" + msg);
    }
}

解释

观察者接口(Observer):定义了观察者接收消息的方法 update。所有具体观察者只要实现这个接口,就可以接收被观察者发送的消息。

被观察者接口(Subject):定义了注册观察者、移除观察者和通知观察者的方法。这样可以统一管理观察者对象。

具体被观察者类(ConcreteSubject):内部维护了一个 observers 集合,用于保存所有注册进来的观察者。当调用 notifyObservers 方法时,会遍历 observers 集合,并调用每个观察者的 update 方法。

具体观察者类(ConcreteObserver):保存了观察者名称,并实现了 update 方法。当收到消息时,会打印当前观察者收到的消息内容。

通过这种方式,ConcreteSubject 不需要知道每个观察者的具体业务逻辑,只需要负责通知即可。如果后续需要增加新的观察者类型,只要实现 Observer 接口即可,不需要修改 ConcreteSubject 的核心逻辑。

测试

System.out.println("------------------------------观察者模式-----------------------------");
ConcreteSubject concreteSubject = new ConcreteSubject();
ConcreteObserver zhangSan = new ConcreteObserver("张三");
ConcreteObserver liSi = new ConcreteObserver("李四");
ConcreteObserver wangWu = new ConcreteObserver("王五");
concreteSubject.registerObserver(zhangSan);
concreteSubject.registerObserver(liSi);
concreteSubject.registerObserver(wangWu);
concreteSubject.notifyObservers("你好");
concreteSubject.removeObserver(liSi);
concreteSubject.notifyObservers("悄悄话,不要让李四看到");

输出结果

------------------------------观察者模式-----------------------------
张三 收到的消息是:你好
李四 收到的消息是:你好
王五 收到的消息是:你好
张三 收到的消息是:悄悄话,不要让李四看到
王五 收到的消息是:悄悄话,不要让李四看到

结语

观察者模式通过注册、移除和通知观察者的方式,实现了对象之间的一对多通知关系。被观察者只负责维护观察者列表并发送通知,观察者只负责接收消息并处理自己的逻辑。

在实际开发中,观察者模式常用于消息通知、事件监听、订阅发布等场景。合理使用观察者模式,可以降低对象之间的耦合度,也能让系统在新增通知对象时更加灵活。

0

回到顶部