当前位置: 首页 > article >正文

行为型-观察者模式

文章目录

  • 基本概念
    • 定义
    • 使用场景
    • 代码实现
  • 延伸阅读
    • java监听机制
    • spring监听机制

基本概念

定义

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
观察者模式(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);
    }
}

http://www.kler.cn/a/273565.html

相关文章:

  • WordPress之generatepress主题安装
  • Claude 3.5 Sonnet模型新增了PDF支持功能
  • 如何让网页中的图片不可下载,让文字不可选中/复制
  • EJEAS S2滑雪对讲机全球发布会圆满举办,为滑雪市场注入新活力
  • 项目解决方案:跨不同的物理网络实现视频监控多画面的实时视频的顺畅访问
  • IDEA - 快速去除 mapper.xml 黄色警告线和背景色----简化版
  • 递归方法构建哈夫曼树
  • C语言calloc函数的特点,效率低。但是进行初始化操作
  • V-JEPA模型,非LLM另外的选择,AGI的未来:迈向Yann LeCun先进机器智能(AMI)愿景的下一步
  • IPC之管道
  • Android14之HIDL报错:Invalid sparse file format at header magic(一百九十六)
  • RHCE——三:Web服务器(内网穿透实验)
  • transferto转换文件类型报错
  • Auto-DataProcessing:一组让制作数据集变轻松的脚本
  • 显示android设备所以已安装App 可点击启动、搜索
  • Halcon 点云处理流程(点云分割、连通筛选、模型位姿变换、三角化)
  • Linux命令-dhclient命令(动态获取或释放IP地址)
  • 前后端分离项目部署服务器教程--实践成功
  • 【简历篇】如何写简历(二)简历元素、技巧、规范、三省
  • Git——GitHub远端协作详解
  • Apache Doris 如何基于自增列满足高效字典编码等典型场景需求
  • 在Hive中使用Python编写的UDF函数
  • 全量知识系统 微服务及特征复数空间和立体逻辑方阵的设想及百度AI回复
  • MySql安装与卸载—我耀学IT
  • 小程序云开发(十六):JavaScript基础
  • 浅谈Java 编程语言