14 设计模式值观察者模式(书籍发布通知案例)

一、观察者模式定义

在日常开发中,我们经常会遇到一种场景:某个对象的状态发生变化时,需要通知并更新其他相关对象。这时,观察者模式便成为了解决问题的有效方案。观察者模式是一种常见的设计模式,它允许一个对象的状态变化自动通知依赖于它的其他对象。

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

换句话说,观察者模式允许一个对象(称为被观察者 )将其状态的变化推送给多个观察者(观察者),而观察者则根据状态变化做出相应的处理。


二、观察者模式组成

观察者模式包含以下几个重要组成部分:

1.Subject(主题/被观察者)

被观察者是状态变化的源头,它会维护一组观察者对象。

被观察者提供接口让观察者注册、注销,并在状态发生变化时通知观察者。

2.Observer(观察者)

观察者是依赖于被观察者的对象,当被观察者的状态发生变化时,观察者会接收到通知并做出相应的处理。

观察者接口通常定义一个 update 方法,用于接受通知。

3.ConcreteSubject(具体被观察者)

具体被观察者实现了 Subject 接口,并在状态变化时通知所有已注册的观察者。

4.ConcreteObserver(具体观察者)

具体观察者实现了 Observer 接口,并在接收到通知时更新自身的状态。


三、观察者模式的工作原理

在观察者模式中,被观察者 通过 register 方法注册多个观察者。被观察者的状态一旦发生变化,调用 notify 方法将通知所有已注册的观察者,观察者会通过 update 方法接收并处理这些变化。


四、案例讲解:书籍发布通知

为了更好地理解观察者模式,下面我们通过一个书籍发布通知的例子来演示观察者模式的实际应用。

1. 设计接口与类

在本例中,我们将书籍发布看作是被观察者,而读者则是观察者。当新书发布时,我们需要通知所有注册的读者,告诉他们新书的名字。

(1)Observer 接口

java 复制代码
public interface Observer {
    void update(String bookName);
}

Observer 接口定义了一个 update 方法,用于接收新书发布的通知,并通过书名来更新观察者的状态。

(2)ConcreteObserver

java 复制代码
public class ConcreteObserver implements Observer {
    private String readerName;

    public ConcreteObserver(String readerName) {
        this.readerName = readerName;
    }

    @Override
    public void update(String bookName) {
        System.out.println(readerName + ", 收到新书发布通知:" + bookName);
    }
}

ConcreteObserver 是具体的观察者类,它保存读者的姓名,并在接收到新书发布通知时,输出一条消息来告诉读者。

(3)Subject 接口

java 复制代码
public interface Subject {
    void registerObserver(Observer observer);  // 注册观察者
    void removeObserver(Observer observer);    // 移除观察者
    void notifyObservers();                    // 通知观察者
}

Subject 接口定义了三个方法:注册观察者、移除观察者和通知所有观察者。

(4)ConcreteSubject

java 复制代码
public class ConcreteSubject implements Subject {
    private List<Observer> observers;
    private String bookName;

    public ConcreteSubject() {
        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() {
        for (Observer observer : observers) {
            observer.update(bookName);
        }
    }

    // 新书发布方法,更新书名并通知所有观察者
    public void publishBook(String bookName) {
        this.bookName = bookName;
        notifyObservers();
    }
}

ConcreteSubject 类实现了 Subject 接口。它维护一个观察者列表,并在新书发布时通知所有已注册的观察者。

2.测试类

java 复制代码
public class TestObserverPattern {
    public static void main(String[] args) {
        ConcreteSubject bookPublisher = new ConcreteSubject();
        Observer reader1 = new ConcreteObserver("Theodore_1022");
        Observer reader2 = new ConcreteObserver("Andy");
        Observer reader3 = new ConcreteObserver("小胖");

        bookPublisher.registerObserver(reader1);
        bookPublisher.registerObserver(reader2);
        bookPublisher.registerObserver(reader3);

        System.out.println("发布新书:超越音符");
        bookPublisher.publishBook("超越音符");

        bookPublisher.removeObserver(reader2);

        System.out.println("发布新书:记得");
        bookPublisher.publishBook("记得");
    }
}

3. 运行输出

发布新书:超越音符

Theodore_1022, 收到新书发布通知:超越音符

Andy, 收到新书发布通知:超越音符

小胖, 收到新书发布通知:超越音符

发布新书:记得

Theodore_1022, 收到新书发布通知:记得

小胖, 收到新书发布通知:记得


五、观察者模式的优缺点

1.优点

  • 松耦合 :观察者模式将观察者与被观察者解耦。被观察者不需要知道观察者的具体实现,只需要调用 update 方法。
  • 动态更新:可以动态地添加或删除观察者,系统可以根据需要进行扩展。
  • 适用于一对多的场景:当一个对象的状态变化需要同时影响多个对象时,观察者模式是理想的选择。

2.缺点

  • 通知过多:当观察者较多时,通知会影响性能。如果被观察者频繁发生变化,可能会引发性能问题。
  • 依赖过度:观察者模式会导致观察者过于依赖被观察者的实现,可能会影响代码的灵活性。

六、总结

观察者模式是一种非常适合"一对多"场景的设计模式。在需要解耦的场景中,它为对象之间的通信提供了灵活、低耦合的方式。本次案例中,我们通过"书籍发布"的实际例子,清晰地展示了如何实现观察者模式,并将模式的各个组成部分一一拆解。

通过实现观察者模式,我们能够在系统中自动管理对象间的依赖关系,确保在状态变化时,系统能够自动进行更新,而无需手动干预。这使得代码的扩展性和可维护性得到了显著提升。

相关推荐
Java技术小馆几秒前
SpringBoot中暗藏的设计模式
java·面试·架构
xiguolangzi1 分钟前
《springBoot3 中使用redis》
java
Aniugel3 分钟前
JavaScript高级面试题
javascript·设计模式·面试
꧁坚持很酷꧂4 分钟前
配置Ubuntu18.04中的Qt Creator为中文(图文详解)
开发语言·qt·ubuntu
李菠菜8 分钟前
非SpringBoot环境下Jedis集群操作Redis实战指南
java·redis
不当菜虚困21 分钟前
JAVA设计模式——(四)门面模式
java·开发语言·设计模式
ruyingcai66666621 分钟前
用python进行OCR识别
开发语言·python·ocr
Niuguangshuo24 分钟前
Python设计模式:MVC模式
python·设计模式·mvc
BB_CC_DD24 分钟前
四. 以Annoy算法建树的方式聚类清洗图像数据集,一次建树,无限次聚类搜索,提升聚类搜索效率。(附完整代码)
深度学习·算法·聚类
m0Java门徒29 分钟前
面向对象编程核心:封装、继承、多态与 static 关键字深度解析
java·运维·开发语言·intellij-idea·idea