js全局的发布——订阅模式

本文介绍了如何使用全局的Event对象实现发布-订阅模式,以此解决资源浪费和对象耦合的问题。通过一个中介者角色的Event对象,订阅者无需知道发布者,发布者也无需关心接收者,实现了松耦合的事件通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<h1>全局的发布——订阅</h1>
   <p>回想上一章的通用的发布—订阅模式,我们给Event对象及saleOffices对象都添加了订阅—发布的功能,这里存在两个问题。</p>
   <p>1.我们给每个发布者对象都添加了listen和trigger方法,以及一个缓存列表clientList,这其实是一种资源浪费。</p>
   <p>2.小明跟售楼处对象还是存在一定的耦合性,小明至少要知道售楼处对象的名字是saleOffices,才能顺利的订阅到事件</p>
   <p>事实上,发布——订阅模式可以用一个全局的Event对象来实现,订阅者不需要了解消息来自哪个发布者,发布者也不需要消息会推送到哪些订阅者,
   Event作为一个类似”中介者“的角色,把订阅者和发布者联系起来。代码如下:</p>
   <script>
      var Event = (function(){
         var clientList = {},
             listen,
             trigger,
             remove;
         
         listen = function( key, fn ){
            if( !clientList[ key ] ){
               clientList[ key ] = [];
            };
            clientList[ key ].push( fn );
         };
         
         trigger = function(){
             var key = Array.prototype.shift.apply( arguments ),
                 fns = clientList[ key ];
             if( !fns || fns.length === 0 ){
               return false;
             }
             for( var i = 0, fn; fn = fns[ i++ ]; ){
                fn.apply( this, arguments )
             }
         };
         
         remove = function( key, fn){
             var fns = clientList[ key ];
             if( !fns ){
                return false;
             }
             if( !fn ){
                clientList[ key ] = [];
             }else{
                for( var i = 0; i < fns.length; i++ ){
                   if( fn === fns[ i ]){
                      fns.splice( i, 1);
                   }
                }
             }
         };
         
         return {
            listen: listen,
            trigger: trigger,
            remove: remove
         }
      }());
      
      Event.listen( "squareMeter88", fn1 = function( price ){
         console.log( price );
      } );
      Event.remove( "squareMeter88",fn1 );
      Event.trigger( "squareMeter88", 200000 );
      
   </script>

### 发布订阅模式的实现与应用 #### 什么是发布订阅模式发布订阅模式是一种设计模式,用于解耦对象之间的依赖关系。它允许订阅者注册感兴趣的事件,并由调度中心管理这些订阅信息。当发布者触发某一事件时,调度中心会通知所有对该事件感兴趣的订阅者并调用它们的回调函数[^1]。 --- #### 发布订阅模式的核心组成部分 1. **发布者(Publisher)**:负责创建发送事件。 2. **订阅者(Subscriber)**:监听特定事件并通过回调函数接收通知。 3. **调度中心(Event Bus/Topic Center)**:充当中介角色,存储订阅者的回调函数并与发布者交互。 这种模式的特点在于全局可用性低耦合性,使得不同模块可以独立开发而无需相互了解具体细节[^2]。 --- #### JavaScript中的发布订阅模式实现示例 以下是基于JavaScript的一个简单实现: ```javascript // 定义事件总线类 class EventBus { constructor() { this.subscribers = {}; // 存储订阅者及其对应的回调函数 } // 订阅方法 subscribe(eventType, callback) { if (!this.subscribers[eventType]) { this.subscribers[eventType] = []; } this.subscribers[eventType].push(callback); } // 取消订阅方法 unsubscribe(eventType, callbackToRemove) { if (this.subscribers[eventType]) { this.subscribers[eventType] = this.subscribers[eventType].filter( cb => cb !== callbackToRemove ); } } // 发布方法 publish(eventType, ...args) { if (this.subscribers[eventType]) { this.subscribers[eventType].forEach(callback => callback(...args)); } } } // 使用示例 const eventBus = new EventBus(); function user1(data) { console.log("User1 received:", data); } function user2(data) { console.log("User2 received:", data); } eventBus.subscribe("message", user1); // 用户1订阅消息 eventBus.subscribe("message", user2); // 用户2订阅消息 eventBus.publish("message", "Hello from Publisher!"); // 发布消息 ``` 在这个例子中,`EventBus` 类作为一个调度中心,提供了 `subscribe`、`unsubscribe` `publish` 方法来支持订阅、取消订阅以及发布功能[^3]。 --- #### Java中的发布订阅模式实现示例 下面展示了一个Java版本的实现方式: ```java import java.util.ArrayList; import java.util.List; interface Receiver { void onMessage(String publisher, String message); } class Subscriber { private final String name; private final Receiver receiver; public Subscriber(String name, Receiver receiver) { this.name = name; this.receiver = receiver; } public Receiver getReceiver() { return receiver; } } class EventBus { private final List<Subscriber> subscribers = new ArrayList<>(); private final String publisherName; public EventBus(String publisherName) { this.publisherName = publisherName; } public void addSubscriber(Subscriber subscriber) { subscribers.add(subscriber); } public void removeSubscriber(Subscriber subscriber) { subscribers.remove(subscriber); } public void notifySubscribers(String message) { for (Subscriber subscriber : subscribers) { subscriber.getReceiver().onMessage(this.publisherName, message); } } } public class Main { public static void main(String[] args) { Subscriber sub1 = new Subscriber("Alice", (publisher, msg) -> System.out.println(publisher + ": " + msg)); Subscriber sub2 = new Subscriber("Bob", (publisher, msg) -> System.out.println(publisher + ": " + msg)); EventBus eventBus = new EventBus("News Channel"); eventBus.addSubscriber(sub1); eventBus.addSubscriber(sub2); eventBus.notifySubscribers("Breaking News!"); } } ``` 这段代码展示了如何通过接口定义接收器逻辑,并让多个订阅者绑定到同一个发布者上[^4]。 --- #### 发布订阅模式的应用场景 1. **前端框架中的响应式编程** 如 Vue 的数据双向绑定机制就是基于此模式实现的。视图组件作为订阅者,模型变化时会自动更新界面显示[^1]。 2. **跨平台通信协议** MQTT 协议广泛应用于物联网领域,其中的主题(Topic)概念正是发布订阅模式的具体体现[^2]。 3. **桌面应用程序的通知系统** Windows 或 macOS 上的任务栏图标闪烁提醒也遵循类似的思路——程序状态发生变化后向操作系统发出信号以便提示用户注意[^5]。 4. **服务器端事件驱动架构** Node.js 的 `EventEmitter` 是另一个典型代表,开发者可以通过自定义事件完成复杂的异步流程控制[^3]。 --- #### 总结 无论是前端还是后端开发,亦或是分布式系统的构建过程中,合理运用发布订阅模式能够显著提升代码可维护性扩展能力的同时降低各部分间的紧密联系程度。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值