行为型-观察者模式

基本概念

定义

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。
观察者模式包含以下几个核心角色:
主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。
观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察者都会收到通知并进行相应的更新。

使用场景

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。通过这种事件触发的机制,将观察者和被观察者进行解耦。
注意事项:
1、JAVA 中已经有了对观察者模式的支持类。(Java中EventObject、EventListener)
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

代码实现

主题接口

/**
 * 抽象主题(抽象被观察者角色)
 */
public interface Subject {

    /**
     * 所有抽象观察者角色的集合
     */
    List<Observer> observerList = Lists.newArrayList();

    /**
     * 注册观察者
     * @param observer
     */
    default void addObserver(Observer observer){
        observerList.add(observer);
    }

    /**
     * 取消注册
     * @param observer
     */
    default void removeObserver(Observer observer){
        observerList.remove(observer);
    }

    /**
     * 通知所有观察者
     * @param content
     */
    default void notifyAllObserver(String content){
        for (Observer observer: observerList){
            observer.recvMsg(content);
        }
    }

}

观察者接口

/**
 * 观察者
 */
public interface Observer {

    void recvMsg(String content);
}

具体被观察者

@Data
public class ConcreteSubject implements Subject<Observer> {

    private String msg;

    /**
     * 发送通知
     */
    public void sendMsg(){
        System.out.println("ConcreteSubject send msg: " + this.msg);
        notifyAllObserver(msg);
    }
}

具体观察者

public class ConcreteObserver implements Observer {
    @Override
    public void recvMsg(String content) {
        System.out.println("ConcreteObserver recv msg:" + content);
    }
}

测试

public class ObserverTest {

    public static void main(String[] args) {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        concreteSubject.setMsg("important msg");
        concreteSubject.addObserver(new ConcreteObserver());
        concreteSubject.sendMsg();
    }
}

延伸阅读

java监听机制

一、创建事件对象

public class MusicEvent extends EventObject {


    public static final int STATE_OPEN = 1;

    public static final int STATE_CLOSE = -1;
    /**
     * 状态
     */
    private int state;

    /**
     * Constructs a prototypical Event.
     *
     * @param source the object on which the Event initially occurred
     * @throws IllegalArgumentException if source is null
     */
    public MusicEvent(Object source) {
        super(source);
    }

    public MusicEvent(Object source, int state) {
        super(source);
        this.state = state;
    }

    public int getState() {
        return state;
    }

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

二、创建监听器

public interface MusicListener extends EventListener {

    void play(MusicEvent musicEvent);
}

CloseMusicListener实现

public class CloseMusicListener implements MusicListener{
    @Override
    public void play(MusicEvent musicEvent) {
        if(musicEvent.getState() == MusicEvent.STATE_CLOSE){
            System.out.println("CloseMusicListener play: stop dance");
        }
    }
}

OpenMusicListener实现

public class OpenMusicListener implements MusicListener{
    @Override
    public void play(MusicEvent musicEvent) {
        if(musicEvent.getState() == MusicEvent.STATE_OPEN){
            System.out.println("OpenMusicListener play: let us go dancing!");
        }
    }
}

三、定义事件源,管理监听器

public class EventSource {

    // 监听器列表,监听器注册入此列表
    public List<MusicListener> musicListenerList = new ArrayList<>();


    // 注册监听器
    public void addMusicListener(MusicListener musicListener) {
        musicListenerList.add(musicListener);
    }

    // 取消注册
    public void removeMusicListener(MusicListener musicListener) {
        musicListenerList.remove(musicListener);
    }

    // 接收外部事件
    public void notifyMusicListener(MusicEvent musicEvent) {
        for (MusicListener musicListener : musicListenerList){
            musicListener.play(musicEvent);
        }
    }
}

四、测试

public class MusicEventTest {
    public static void main(String[] args) {
        EventSource eventSource = new EventSource();
        eventSource.addMusicListener(new OpenMusicListener());
        eventSource.addMusicListener(new CloseMusicListener());

        eventSource.notifyMusicListener(new MusicEvent("开门事件", MusicEvent.STATE_OPEN));
    }
}

spring监听机制

一、创建事件对象,继承ApplicationEvent

@EqualsAndHashCode(callSuper = true)
public class MyEvent extends ApplicationEvent {

    private String context;

    public MyEvent(Object source) {
        super(source);
    }

    public String getContext() {
        return context;
    }

    public void setContext(String context) {
        this.context = context;
    }
}

二、定义监听器,实现ApplicationListener
MyApplication1

public class MyApplication1 implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        System.out.println("MyApplication1 event:" + myEvent.getContext());
    }
}

MyApplication2

public class MyApplication2 implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        System.out.println("MyApplication2 event:" + myEvent.getContext());
    }
}

三、事件通知

@Service
public class MyListenerService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void register(MyEvent event){
        applicationEventPublisher.publishEvent(event);
    }
}

相关推荐

  1. 行为-观察模式

    2024-03-18 19:54:01       50 阅读
  2. 行为-观察模式(Observer)

    2024-03-18 19:54:01       33 阅读
  3. 设计模式_行为模式_观察模式

    2024-03-18 19:54:01       64 阅读
  4. 设计模式_行为模式_观察模式

    2024-03-18 19:54:01       62 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-18 19:54:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-18 19:54:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-18 19:54:01       87 阅读
  4. Python语言-面向对象

    2024-03-18 19:54:01       96 阅读

热门阅读

  1. 习题6-4 使用函数输出指定范围内的Fibonacci数

    2024-03-18 19:54:01       40 阅读
  2. 量化交易入门(四)Python开发-基本语法

    2024-03-18 19:54:01       43 阅读
  3. nginx应用场景(附配置)

    2024-03-18 19:54:01       40 阅读
  4. Websocket 中的 sub-protocol 和 extensions 的关系

    2024-03-18 19:54:01       48 阅读
  5. 机器学习复习(9)——自定义dataset

    2024-03-18 19:54:01       40 阅读
  6. 【详细带你了解软件系统架构的演变】

    2024-03-18 19:54:01       38 阅读
  7. Linux文件内容显示

    2024-03-18 19:54:01       38 阅读
  8. elementUi自定义表头,根据判断显示不同的表头

    2024-03-18 19:54:01       44 阅读
  9. 蓝桥杯(3.17 刷真题)

    2024-03-18 19:54:01       43 阅读
  10. 20240317Python练习代码

    2024-03-18 19:54:01       41 阅读