概述
观察者模式又叫发布 – 订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个目标对象(为了方便理解,以下将观察者对象叫做订阅者,将目标对象叫做发布者)。发布者的状态发生变化时就会通知所有的订阅者,使得它们能够自动更新自己。
观察者模式的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
观察者模式的中心思想就是促进松散耦合,一为时间上的解耦,二为对象之间的解耦。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响到另一边的变化。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
(function (window, undefined) { var _subscribe = null, _publish = null, _unsubscribe = null, _shift = Array.prototype.shift, // 删除数组的第一个 元素,并返回这个元素 _unshift = Array.prototype.unshift, // 在数组的开头添加一个或者多个元素,并返回数组新的length值 namespaceCache = {}, _create = null, each = function (ary, fn) { var ret = null; for (var i = 0, len = ary.length; i < len; i++) { var n = ary[i]; ret = fn.call(n, i, n); } return ret; }; // 订阅消息 _subscribe = function (key, fn, cache) { if (!cache[key]) { cache[key] = []; } cache[key].push(fn); }; // 取消订阅(取消全部或者指定消息) _unsubscribe = function (key, cache, fn) { if (cache[key]) { if (fn) { for (var i = cache[key].length; i >= 0; i--) { if (cache[key][i] === fn) { cache[key].splice(i, 1); } } } else { cache[key] = []; } } }; // 发布消息 _publish = function () { var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, ret = null, stack = cache[key]; if (!stack || !stack.length) { return; } return each(stack, function () { return this.apply(_self, args); }); }; // 创建命名空间 _create = function (namespace) { var namespace = namespace || "default"; var cache = {}, offlineStack = {}, // 离线事件,用于先发布后订阅,只执行一次 ret = { subscribe: function (key, fn, last) { _subscribe(key, fn, cache); if (!offlineStack[key]) { offlineStack[key] = null; return; } if (last === "last") { // 指定执行离线队列的最后一个函数,执行完成之后删除 offlineStack[key].length && offlineStack[key].pop()(); // [].pop => 删除一个数组中的最后的一个元素,并且返回这个元素 } else { each(offlineStack[key], function () { this(); }); } offlineStack[key] = null; }, one: function (key, fn, last) { _unsubscribe(key, cache); this.subscribe(key, fn, last); }, unsubscribe: function (key, fn) { _unsubscribe(key, cache, fn); }, publish: function () { var fn = null, args = null, key = _shift.call(arguments), _self = this; _unshift.call(arguments, cache, key); args = arguments; fn = function () { return _publish.apply(_self, args); }; if (offlineStack && offlineStack[key] === undefined) { offlineStack[key] = []; return offlineStack[key].push(fn); } return fn(); } }; return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret; }; window.pubsub = { create: _create, // 创建命名空间 one: function (key, fn, last) { // 订阅消息,只能单一对象订阅 var pubsub = this.create(); pubsub.one(key, fn, last); }, subscribe: function (key, fn, last) { // 订阅消息,可多对象同时订阅 var pubsub = this.create(); pubsub.subscribe(key, fn, last); }, unsubscribe: function (key, fn) { // 取消订阅,(取消全部或指定消息) var pubsub = this.create(); pubsub.unsubscribe(key, fn); }, publish: |