何为观察者模式

观察者模式定义对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。

观察者模式的类图如下所示。

cc8c1b3ad93e53fb1a4fb6981762af7e

示例

比如我自己有一个公众号,公众号每隔一段时间会推送消息(发布者),然后订阅公众号的用户(观察者)可以看到订阅者的消息。

创建一个消息类,包括标题,日期,简要内容。

public class Message {
    private String title;
    private Date date;
    private String content;
}

定义 Subject 接口,有注册订阅者,取消注册订阅者和发布消息。

public interface Subject {

    /**
     * 注册订阅者
     *
     * @param observer
     */
    void attach(Observer observer);

    /**
     * 取消注册订阅者
     *
     * @param observer
     */
    void detach(Observer observer);

    /**
     * 通知
     */
    void notifyObserver();

}

定义观察者接口,主要接收来自 Subject 发布的消息。

public interface Observer {
    void update(Message message);
}

实现 Subject 接口。

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MyWxSubject implements Subject {

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

    private Message message = new Message();

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

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

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

    public void setMessage(String title, String content) {
        message.setDate(new Date());
        message.setTitle(title);
        message.setContent(content);
        // 发布消息,通知订阅者(观察者)
        notifyObserver();
    }
}

实现观察者接口。

public class Observer1 implements Observer {

    private String username;

    public Observer1(String username) {
        this.username = username;
    }

    /**
     * 接收来自订阅者的消息
     *
     * @param message 消息实体类
     */
    @Override
    public void update(Message message) {
        System.out.println(username + ",收到的消息如下");
        System.out.println(message);
    }

}

测试一下

public class ObserverTest {

    public static void main(String[] args) {
        MyWxSubject myWxSubject = new MyWxSubject();

        Observer1 zhangsan = new Observer1("zhangsan");
        Observer1 lisi = new Observer1("lisi");
        Observer1 wangwu = new Observer1("wangwu");

        // 注册消息
        myWxSubject.attach(zhangsan);
        myWxSubject.attach(lisi);
        myWxSubject.attach(wangwu);

        myWxSubject.setMessage("观察模式", "观察者模式定义对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。");

        System.out.println("======================================");

        // 李四不订阅了
        myWxSubject.detach(lisi);
        myWxSubject.setMessage("单例模式", "确保类只有一个实例,并提供一个全局的访问点");
    }

}

运行一下

zhangsan,收到的消息如下
Message(title=观察模式, date=Wed Mar 15 17:11:28 CST 2023, content=观察者模式定义对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。)
lisi,收到的消息如下
Message(title=观察模式, date=Wed Mar 15 17:11:28 CST 2023, content=观察者模式定义对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。)
wangwu,收到的消息如下
Message(title=观察模式, date=Wed Mar 15 17:11:28 CST 2023, content=观察者模式定义对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。)
======================================
zhangsan,收到的消息如下
Message(title=单例模式, date=Wed Mar 15 17:11:28 CST 2023, content=确保类只有一个实例,并提供一个全局的访问点)
wangwu,收到的消息如下
Message(title=单例模式, date=Wed Mar 15 17:11:28 CST 2023, content=确保类只有一个实例,并提供一个全局的访问点)