博客
关于我
《JavaScript设计模式与开发实践》笔记第八章 发布-订阅模式
阅读量:429 次
发布时间:2019-03-06

本文共 3174 字,大约阅读时间需要 10 分钟。

发布-订阅模式:从基础到实践

发布-订阅模式(Observer Pattern)是一种常见的设计模式,主要用于处理对象间的一对多关系。当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知。这种模式在异步编程中尤为重要,能够有效替代传递回调函数的方式,使代码更加松耦合。

发布-订阅模式的核心优势

  • 松耦合性:发布者和订阅者之间不需要直接耦合,只需通过事件名称进行通信。
  • 灵活性:订阅者可以随时加入或退出,无需修改发布者的代码。
  • 异步性:适合处理异步操作,避免了回调链的复杂性。
  • DOM事件与自定义事件

    在前言中提到,DOM事件可以被看作是发布-订阅模式的简单实现。每当在DOM节点上绑定事件时,就相当于创建了一个发布-订阅关系。当事件发生时,所有绑定的回调函数都会被调用。

    此外,自定义事件是实现发布-订阅模式的重要工具。通过自定义事件,我们可以在任何JavaScript代码中灵活地管理事件传播。

    优雅实现发布-订阅模式

    要实现发布-订阅模式,可以按照以下步骤进行:

  • 指定发布者:通常选择一个专门的对象(如salesOffices)作为发布者。
  • 维护订阅列表:在发布者对象中创建一个缓存列表,存储所有订阅者的回调函数。
  • 订阅事件:订阅者通过listen方法将自己的回调函数添加到缓存列表中。
  • 发布事件:发布者通过trigger方法遍历缓存列表,调用所有订阅者的回调函数。
  • 为了提高效率,可以在回调函数中添加标识符,确保订阅者只接收感兴趣的消息。例如,小明只订阅88平方米的房子信息,而不需要处理110平方米的消息。

    实际应用案例

    网站登录示例

    在一个商城网站中,header、nav、消息列表等模块需要获取用户的登录信息。为了实现这一目标,我们可以使用发布-订阅模式:

  • 登录信息发布:通过AJAX调用登录接口,获取用户数据后,触发loginSucc事件。
  • 事件订阅:各个模块通过listen方法订阅loginSucc事件,分别处理登录信息。
  • 模块间通信:每个模块可以独立地处理登录信息,而无需了解其他模块的具体实现。
  • 模块间通信示例

    为了实现模块间通信,可以基于一个全局的Event对象:

    // 全局Event对象
    var Event = {
    clientList: {},
    listen: function(key, fn) {
    if (!Event.clientList[key]) {
    Event.clientList[key] = [];
    }
    Event.clientList[key].push(fn);
    },
    trigger: function() {
    var key = Array.prototype.shift.call(arguments);
    var fns = Event.clientList[key];
    if (!fns || fns.length === 0) {
    return false;
    }
    for (var i = 0; i < fns.length; i++) {
    fns[i].apply(this, arguments);
    }
    }
    };
    // 模块A订阅事件
    Event.listen('add', function(count) {
    console.log('点击次数:', count);
    });
    // 模块B订阅事件
    Event.listen('add', function(count) {
    document.getElementById('show').innerHTML = count;
    });
    // 模块A触发事件
    button.onclick = function() {
    Event.trigger('add', count);
    };

    先订阅再发布

    在实际应用中,有时候发布事件的对象在订阅事件的对象尚未准备好。这种情况下,可以采用先保存事件再发布的方式:

    // 保存事件
    eventStack.push(function() {
    Event.trigger('saveData');
    });
    // 发布事件
    Event.trigger('saveData');

    这种方式类似于QQ的离线消息处理,确保即使发布者尚未订阅事件,事件也能在适当的时候被处理。

    命名空间的管理

    为了避免全局事件名冲突,可以为事件创建命名空间:

    var Event = (function() {
    var namespaces = {},
    clientList = {},
    listen = function(key, fn) {
    if (!namespaces[key]) {
    namespaces[key] = { clientList: [] };
    }
    namespaces[key].clientList.push(fn);
    };
    var trigger = function() {
    var key = Array.prototype.shift.call(arguments);
    var ns = key.split('.').shift();
    var clientList = namespaces[ns] ? namespaces[ns].clientList : [];
    if (!clientList || clientList.length === 0) {
    return false;
    }
    for (var i = 0; i < clientList.length; i++) {
    clientList[i].apply(this, arguments);
    }
    };
    return {
    create: function(namespace) {
    namespaces[namespace] = {
    clientList: []
    };
    return {
    listen: function(key, fn) {
    listen(key, fn, namespace);
    },
    trigger: function() {
    trigger.apply(this, arguments, namespace);
    }
    };
    }
    };
    })();
    Event.create('namespace1').listen('click', function(a) {
    console.log(a);
    });
    Event.create('namespace2').listen('click', function(a) {
    console.log(a);
    });
    Event.create('namespace1').trigger('click', 1);
    Event.create('namespace2').trigger('click', 2);

    总结

    发布-订阅模式是一种强大的设计模式,能够有效地处理对象间的松耦合通信。在实际应用中,可以通过全局Event对象实现模块间通信,确保各模块保持高度封装。同时,通过命名空间管理,可以有效避免全局事件名冲突,提升代码的可维护性和扩展性。

    转载地址:http://edouz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现bitonic sort双调排序算法(附完整源码)
    查看>>
    Objective-C实现BloomFilter布隆过滤器的算法(附完整源码)
    查看>>
    Objective-C实现BMP图像旋转180度(附完整源码)
    查看>>
    Objective-C实现bogo sort排序算法(附完整源码)
    查看>>
    Objective-C实现boruvka博鲁夫卡算法(附完整源码)
    查看>>
    Objective-C实现Boyer-Moore字符串搜索算法(附完整源码)
    查看>>
    Objective-C实现BP误差逆传播算法(附完整源码)
    查看>>
    Objective-C实现breadth First Search广度优先搜索算法(附完整源码))
    查看>>
    Objective-C实现BreadthFirstSearch广度优先搜索算法(附完整源码)
    查看>>
    Objective-C实现BreadthFirstShortestPath广度优先最短路径算法(附完整源码)
    查看>>
    Objective-C实现bubble sort冒泡排序算法(附完整源码)
    查看>>
    Objective-C实现bucket sort桶排序算法(附完整源码)
    查看>>
    Objective-C实现Burke 抖动算法(附完整源码)
    查看>>
    Objective-C实现Burrows-Wheeler 算法(附完整源码)
    查看>>
    Objective-C实现CaesarsCiphe凯撒密码算法(附完整源码)
    查看>>
    Objective-C实现calloc函数功能(附完整源码)
    查看>>
    Objective-C实现canny边缘检测算法(附完整源码)
    查看>>
    Objective-C实现cartesianProduct笛卡尔乘积算法(附完整源码)
    查看>>
    Objective-C实现check strong password检查密码强度算法(附完整源码)
    查看>>
    Objective-C实现chudnovsky algorithm楚德诺夫斯基算法(附完整源码)
    查看>>