观察者模式, 发布-订阅模式, 监听器模式

这篇具有很好参考价值的文章主要介绍了观察者模式, 发布-订阅模式, 监听器模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

观察者模式, 发布-订阅模式, 监听器模式

观察者模式

观察者模式是一种行为型设计模式, 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

角色模型和结构图

在观察者模式中,只有两种主体:目标对象 (Object) 和 观察者 (Observer)。宗门任务大殿就是目标对象,弟子们就是观察者。

  • Subject(主题): 主题是被观察的对象,它维护了一个观察者列表,并提供了添加、删除和通知观察者的方法
  • Observer(观察者): 观察者是订阅主题对象的对象,当主题对象的状态发生变化时,观察者会接收到通知并进行相应的处理。

结构图如下
观察者模式, 发布-订阅模式, 监听器模式,设计模式,观察者模式,java,开发语言

代码实现

观察者抽象接口-Observer
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 抽象观察者接口
 */
public interface Observer {
    /**
     * 发生改变时发送的message
     * @param message 发送的message
     */
    void update(Object message);
}
主题-Subject
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 主题
 */
public interface Subject {
    /**
     * 主题新增观察者
     * @param observer 要注册的Observer
     */
    void registerObserver(Observer observer);

    /**
     * 移除主题下的观察者
     * @param observer 要移除的Observer
     */
    void removeObserver(Observer observer);

    /**
     * 通知该主题所有的Observer
     * @param message 通知内容
     */
    void notifyObservers(Object message);
}
Observer实现类-User
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 微信公众号的具体观察者即用户User
 */
public class User implements Observer {

    /**
     * 用户姓名
     */
    private final String name;

    /**
     * 接受的消息
     */
    private Object message;

    public User(String name) {
        this.name = name;
    }

    /**
     * 确认消息
     */
    public void read() {
        System.out.println(name + "收到推送消息: " + message);
    }

    /**
     * @param message 发送的message
     */
    @Override
    public void update(Object message) {
        this.message = message;
        read();
    }
}

####Subject实现类- WechatServer

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

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 微信公共号
 */
public class WechatServer implements Subject {

    /**
     * 存储Observer的列表
     */
    private final List<Observer> observerList;

    /**
     * 推送的消息
     */
    private Object message;

    public WechatServer() {
        observerList = new ArrayList<>();
    }

    /**
     * @param observer 要注册的Observer
     */
    @Override
    public void registerObserver(Observer observer) {
        // 将Observer添加到列表中
        observerList.add(observer);
    }

    /**
     * @param observer 要移除的Observer
     */
    @Override
    public void removeObserver(Observer observer) {
        // 移除observer
        if (!observerList.isEmpty()) {
            observerList.remove(observer);
        }
    }

    /**
     * @param message 通知内容
     */
    @Override
    public void notifyObservers(Object message) {
        // 遍历被观察者列表,通知每一个Observer
        for (Observer observer : observerList) {
            // 调用update进行通知
            observer.update(message);
        }
    }

    /**
     * 发送微信公众号要推送的消息
     * @param message 要发送的消息
     */
    public void setInformation(Object message) {
        this.message = message;
        System.out.println("微信服务更新消息: " + message);
        // 消息更新,通知所有观察者
        notifyObservers(message);
    }
}
测试类-ObserverModeTest
/**
 * @author whitebrocade
 * @version 1.0
 * @description: Observer测试
 */
public class ObserverModeTest {
    public static void main(String[] args) {
        WechatServer server = new WechatServer();

        Observer jack = new User("Jack");
        Observer smith = new User("Smith");
        Observer kerry = new User("Kerry");

        server.registerObserver(jack);
        server.registerObserver(smith);
        server.registerObserver(kerry);
        server.setInformation("蚁钳是蚁钳, 蟹仔是蟹仔!");

        System.out.println("----------------------------------------------");
        // 将jack从观察者集合中移除
        server.removeObserver(jack);
        server.setInformation("菜就多练, 练就不菜");
    }
}

测试结果如下
观察者模式, 发布-订阅模式, 监听器模式,设计模式,观察者模式,java,开发语言

发布-订阅模式

大概很多人都和我一样,觉得发布订阅模式里的Publisher,就是观察者模式里的Subject,而Subscriber,就是Observer。Publisher变化时,就主动去通知Subscriber。

其实并不是。

在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。之间交流通过Broker进行

角色模型和结构图

  • 发布者(Publisher):负责发布事件或消息到事件总线(Event Bus)中,让订阅者(Subscribers)可以接收到这些事件或消息。
  • EventBus(事件总线):作为发布者和订阅者之间的中介者,负责接收发布者发布的事件,并将事件分发给所有订阅者。事件总线可以是一个独立的组件或者一个消息队列
    • 这里的发布者(事件总线)为一体
  • Subscriber(订阅者): 订阅者订阅感兴趣的消息或事件,并从消息代理中接收相关的消息或事件
  • Event(事件): 事件是发布者发布的消息或事件,订阅者可以根据自己的需求选择订阅特定的事件
    观察者模式, 发布-订阅模式, 监听器模式,设计模式,观察者模式,java,开发语言

代码实现

Event
import lombok.Data;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 抽象事件源
 */
@Data
public abstract class Event {
    /**
     * 事件名
     */
    private String name;

    /**
     * 事件信息
     */
    private Object message;

    /**
     * 事件信息
     */
    private Object type;
}
Subscriber
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 定义订阅者接口
 */
public interface Subscriber {
    /**
     * 事件触发后执行的逻辑
     * @param event 事件
     */
    void handleEvent(Event event);
}
MyEvent
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 自定义事件源
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MyEvent extends Event {
    /**
     * 触发时间
     */
    private Date triggerTime;
}
MySubscriber
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 定义具体订阅者
 */
public class MySubscriber implements Subscriber {
    /**
     * 订阅者名称
     */
    private final String name;

    public MySubscriber(String name) {
        this.name = name;
    }

    @Override
    public void handleEvent(Event event) {
        System.out.println(name + "订阅的事件: " + event.toString());
    }
}
EventBus
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 事件总线
 */
public class EventBus {
    /**
     * k-v存储订阅者名称和订阅者
     */
    private Map<String, List<Subscriber>> subscriberList = new HashMap<>();

    /**
     * 订阅事件
     * @param eventName 事件名
     * @param subscriber 订阅者
     */
    public void subscribe(String eventName, Subscriber subscriber) {
        if (! subscriberList.containsKey(eventName)) {
            subscriberList.put(eventName, new ArrayList<>());
        }
        subscriberList.get(eventName).add(subscriber);
    }

    /**
     * 发布事件
     * @param event 事件
     */
    public void publish(Event event) {
        List<Subscriber> eventSubscribers = subscriberList.get(event.getName());
        if (eventSubscribers != null) {
            for (Subscriber subscriber : eventSubscribers) {
                subscriber.handleEvent(event);
            }
        }
    }
}
测试类
import java.util.Date;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 发布-订阅模式测试类
 */
public class PublisherTest {
    public static void main(String[] args) {
        // 创建事件总线
        EventBus eventBus = new EventBus();


        // 创建订阅者
        Subscriber jack = new MySubscriber("Jack");
        Subscriber tom = new MySubscriber("Tom");

        // 订阅事件
        eventBus.subscribe("event1", jack);
        eventBus.subscribe("event2", tom);

        // 发布事件
        MyEvent event1 = new MyEvent();
        event1.setName("event1");
        event1.setTriggerTime(new Date());
        event1.setMessage("蚁钳是蚁钳, 蟹仔是蟹仔!");
        event1.setType("消息一");
        MyEvent event2 = new MyEvent();
        event2.setName("event2");
        event2.setTriggerTime(new Date());
        event2.setMessage("菜就多练, 练就不菜!");
        event2.setType("消息二");

        eventBus.publish(event1);
        eventBus.publish(event2);
    }
}

测试结果如下
观察者模式, 发布-订阅模式, 监听器模式,设计模式,观察者模式,java,开发语言

观察者模式 和 发布-订阅模式的对比

共同点
  1. 解耦性: 两种模式都能实现发布者与订阅者(观察者)之间的解耦,使得发布者和订阅者可以独立地进行扩展和修改,互不影响。
  2. 事件通知: 在两种模式中,发布者(主题)发生变化时会通知订阅者(观察者),订阅者(观察者)会相应地处理这些事件或通知
区别
  1. 通信机制:
    • 观察者模式: 观察者模式是一对多的通信机制,一个主题对象可以有多个观察者对象订阅它,当主题对象状态发生变化时,所有订阅者都会收到通知
    • 发布-订阅模式: 发布-订阅模式是通过一个消息代理(发布者)来进行通信,发布者将消息发送到消息代理,然后由消息代理将消息分发给所有订阅者。订阅者只需订阅感兴趣的事件,而不需要直接与发布者交互
  2. 关系建立:
    • 观察者模式: 在观察者模式中,观察者需要直接订阅主题对象,主题对象需要维护一个观察者列表
    • 发布-订阅模式: 在发布-订阅模式中,发布者和订阅者之间通过一个消息代理(或事件总线Eventg)进行通信,发布者和订阅者之间不直接建立联系
  3. 灵活性:
    • 观察者模式: 观察者模式在订阅关系上是静态的,即订阅者需要直接订阅特定的主题对象
    • 发布-订阅模式: 发布-订阅模式在订阅关系上是动态的,订阅者可以根据需要订阅不同的事件或消息

监听器模式

监听器模式并不是一个新的设计模式,它是观察者模式在特定场景下的一种改造和应用。通常,观察者模式的主题在通知观察者时,通知中不包含任何信息。如果这个过程中携带了一些其他信息,那么主题本身就成为了事件源,而携带信息的封装类就成为了事件。此时的观察者模式,也就升级为监听器了。监听器模式是观察者模式的另一种形态

角色模型和结构图

监听器模式通常包含三个角色:事件源、事件对象、事件监听器

  • 事件源: 被监听的事件本身, 也就是可以触发监听器的某件事件
  • 事件对象: :事件对象里面存放了对事件源的引用, 可以通过事件对象来获取事件源, 是对事件源的包装
  • 事件监听器: 定义事件发生后的动作

代码实现

Event
import lombok.Data;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 抽象事件源
 */
@Data
public abstract class Event {
    /**
     * 事件信息
     */
    private Object message;

    /**
     * 事件信息
     */
    private Object type;
}
EventListener
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 监听器接口
 */
public interface EventListener {
    /**
     * 事件触发时回调
     * @param event 事件
     */
    void onEventReceived(Event event);
}
EventSource
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 事件源类, 用于注册监听器、触发事件并通知所有监听器
 */
public interface EventSource {

    /**
     * 注册事件监听器
     * @param listener 监听器
     */
    void addListener(EventListener listener);

    /**
     * 移除监听器
     * @param listener 监听器
     */
     void removeListener(EventListener listener);

    /**
     * 事件分发器, 将事件传递给所有注册的事件监听器
     * @param event 事件
     */
    void fireEvent(Event event);
}

MyEvent
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 自定义事件源
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MyEvent extends Event {
    /**
     * 触发时间
     */
    private Date triggerTime;
}
MyListener
/**
 * @author whitebrocade
 * @version 1.0
 * @description: 事件监听器
 */
public class MyListener implements EventListener {
    @Override
    public void onEventReceived(Event event) {
        System.out.println("收到的事件: " + event.toString());
    }
}
MyEventSource
import java.util.ArrayList;
import java.util.List;

/**
 * @author whitebrocade
 * @version 1.0
 * @description: 事件源类, 用于注册监听器、触发事件并通知所有监听器
 */
public class MyEventSource implements EventSource {
    /**
     * 事件源集合
     */
    private List<EventListener> listenerList = new ArrayList<>();

    /**
     * 注册事件监听器
     * @param listener 监听器
     */
    public void addListener(EventListener listener) {
        listenerList.add(listener);
    }

    /**
     * 移除监听器
     * @param listener 监听器
     */
    public void removeListener(EventListener listener) {
        listenerList.remove(listener);
    }

    /**
     * 事件分发器, 将事件传递给所有注册的事件监听器
     * @param event 事件
     */
    public void fireEvent(Event event) {
        for (EventListener listener : listenerList) {
            listener.onEventReceived(event);
        }
    }
}
ListenerTest
import java.util.Date;

/**
 * @author whitebrocade
 * @version 1.0
 * @date 2024/2/21 21:24
 * @description: TODO
 */
public class ListenerTest {
    public static void main(String[] args) {
        // 创建一个事件源
        EventSource eventSource = new MyEventSource();
        // 创建两个事件监听器
        MyListener listener1 = new MyListener();
        MyListener listener2 = new MyListener();
        // 将这两个事件监听器注册到事件源
        eventSource.addListener(listener1);
        eventSource.addListener(listener2);

        // 创建一个事件event
        MyEvent event = new MyEvent();
        event.setTriggerTime(new Date());
        event.setMessage("蚁钳是蚁钳, 蟹仔是蟹仔!");
        event.setType("消息一");
        // 将事件传递给事件源, 进行分发
        eventSource.fireEvent(event);

        // 从事件源中移除一个listener2事件监听器
        eventSource.removeListener(listener2);

        // 再次创建一个事件event2
        MyEvent event2 = new MyEvent();
        event2.setTriggerTime(new Date());
        event2.setMessage("菜就多练, 练就不菜!");
        event2.setType("消息二");
        // 将事件传递给事件源, 进行分发
        eventSource.fireEvent(event2);
    }
}

测试结果如下
观察者模式, 发布-订阅模式, 监听器模式,设计模式,观察者模式,java,开发语言

参考资料

观察者模式 vs 发布订阅模式,千万不要再混淆了

观察者模式 | 菜鸟教程

23 种设计模式详解(全23种)-观察者模式

观察者 - 廖雪峰的官方网站

监听器模式和观察者模式的关系,写点你不知道的

【设计模式】-11监听者模式

【设计模式】-监听者模式和观察者模式的区别与联系_观察者模式和监听者模式的区别

观察者模式 vs 发布订阅模式

[设计模式(四) —— 观察者模式/发布订阅模式](https://blog.csdn.net/weixin_37620587/article/details/130170062#:~:text=1.什么是发布-订阅模式 1 发布-订阅模式是一种行为设计模式,它允许多个对象通过事件的发布和订阅来进行通信; 2,在这种模式中,发布者 (又称为主题)负责发布事件,而订阅者 (也称为观察者)则通过订阅主题来接收这些事件; 3 这种模式使得应用程序的不同部分能够松散耦合,并且可以动态地添加或删除订阅者;)文章来源地址https://www.toymoban.com/news/detail-836342.html

到了这里,关于观察者模式, 发布-订阅模式, 监听器模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 观察者模式、中介者模式和发布订阅模式

    观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新 观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯 例如生活中,我们可以用报

    2024年02月15日
    浏览(49)
  • JavaScript 简单实现观察者模式和发布-订阅模式

    大家好,我是南木元元,热衷分享有趣实用的文章。今天来聊聊设计模式中常用的观察者模式和发布-订阅模式。 观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 如何理解这句话呢?来举个生活中的例子

    2024年02月12日
    浏览(106)
  • 从Vue层面 - 解析发布订阅模式和观察者模式区别

    观察者模式和发布订阅模式作为日常开发中经常使用到的模式,我一直不能做到很好的区分。最近在看Vue的源码,里面设计到了观察者模式,比较感兴趣,就去学习了下,这里做个总结吧。 基于一个 事件中心 ,接收通知的对象是订阅者,需要先订阅某个事件,触发事件的对

    2024年02月15日
    浏览(45)
  • 设计模式(四) —— 观察者模式/发布订阅模式,c和c++示例代码

    往期地址: 设计模式(一)——简单工厂模式 设计模式(二)——策略模式 设计模式(三)——装饰模式 本期主题: 使用c和c++代码,讲解观察者模式、发布订阅模式 发布-订阅模式是一种行为设计模式,它允许多个对象通过事件的发布和订阅来进行通信; 在这种模式中,

    2023年04月17日
    浏览(47)
  • 【JavaScript】手撕前端面试题:寄生组合式继承 | 发布订阅模式 | 观察者模式

    🧑‍💼个人简介:大三学生,一个不甘平庸的平凡人🍬 🖥️ NodeJS专栏:Node.js从入门到精通 🖥️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述) 🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结) 👉

    2023年04月08日
    浏览(95)
  • Unity 事件监听与广播(高度解耦合,观察者模式)

    使用观察者模式降低模块间的耦合性 通过C# 的 Dictionary 存放事件码和事件的委托 添加事件: 判断字典是否有该事件码,没有添加 判断当前委托类型与添加的事件码的类型是否一致 最后订阅该事件 移除事件: 先判断事件码是否存在 取消订阅 最后判断事件码是否为空,是

    2024年02月12日
    浏览(47)
  • 从源码Debug深入spring事件机制,基于观察者模式仿写spring事件监听骨架

    定义一个事件 定义两个listener 注入spring容器里的ApplicationEventPublisher对象,发布事件 从 eventPublisher.publishEvent(new MyEvent(\\\"xxx\\\")); 进去很容易就能找到,可以发现 SimpleApplicationEventMulticaster这个事件发布对象持有所有listenter对象及MyEvent对象 , 事件发布过程其实就是遍历拿到每个li

    2024年02月12日
    浏览(44)
  • 【解决】MissingReferenceException: The object of type ‘GameObject‘ has been destroyed 观察者模式 监听物体被销毁

    MissingReferenceException: The object of type ‘Text’ has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. 该情况发生于我的 观察者模式 在 重新加载当前场景 时 监听的物体被 销毁 如上所示错误,通过分析,定位到错误是在观察

    2024年02月11日
    浏览(49)
  • 【RxJava】RxJava 简介 ( RxJava 概念 | RxJava 组成 - 被观察者 / 观察者 / 订阅 / 操作符 | RxJava 适用场景 )

    RxJava 框架 是一个 异步编程函数库 , 包含了如下要素 : 观察者模式 迭代器模式 函数式编程 RxJava 框架应用场景 : 异步操作 事件流 RxJava 组成要素 : Observable(被观察者): Observable 是一个 可以发送消息的数据源 , 可以同时发送若干消息 , 消息的格式可以通过泛型进行定义 ; 消

    2024年02月06日
    浏览(44)
  • 观察者模式(上):详解各种应用场景下观察者模式的不同实现方式

            从今天起,我们开始学习行为型设计模式。我们知道,创建型设计模式主要解决“对象的创建”问题,结构型设计模式主要解决“类或对象的组合或组装”问题,那行为型设计模式主要解决的就是“ 类或对象之间的交互 ”问题。 原理及应用场景剖析 在对象之间

    2024年02月16日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包