中介者模式(Mediator)

Mediator.js

  1 (function(factory) {
  2     var root = window || (typeof self == 'object' && self.self == self && self);
  3     var Mediator = factory(root);
  4 
  5     root.Mediator = new Mediator();
  6 })(function(root) {
  7 
  8     function Mediator() {
  9         if (!this instanceof Mediator) {
 10             return new Mediator();
 11         } else {
 12             this._topics = new Topic('');
 13         }
 14     }
 15 
 16     Mediator.version = '1.0';
 17 
 18     Mediator.prototype = {
 19         getTopic: function(namespace) {
 20             var topic = this._topics;
 21             var namespaceArr = namespace.split(':');
 22 
 23             if (namespace == '') {
 24                 return topic;
 25             }
 26 
 27             if (namespaceArr.length > 0) {
 28                 for (var i = 0, j = namespaceArr.length; i < j; i++) {
 29                     if (!topic.hasTopic(namespaceArr[i])) {
 30                         topic.addTopic(namespaceArr[i]);
 31                     }
 32                     topic = topic.getTopic(namespaceArr[i]);
 33                 }
 34             }
 35 
 36             return topic;
 37         },
 38         subscribe: function(topicName, fn, options, context) {
 39             var options = options || {},
 40                 context = context || {},
 41                 topic = this.getTopic(topicName);
 42             var sub = topic.addSubscriber(fn, options, context);
 43 
 44             return sub;
 45         },
 46         getSubscriber: function(topicName, id) {
 47             return this.getTopic(topicName || '').getSubscriber(id);
 48         },
 49         removeSubscriber: function(topicName, id) {
 50             this.getTopic(topicName).removeSubscriber(id);
 51         },
 52         publish: function(topicName) {
 53             var args = Array.prototype.slice.call(arguments, 1),
 54                 topic = this.getTopic(topicName);
 55 
 56             args.push(topic);
 57             topic.publish(args);
 58         }
 59     };
 60 
 61     var getID = (function() {
 62         var i = 0;
 63         return function() {
 64             return i++;
 65         }
 66     })();
 67 
 68     function extend(prev, next) {
 69         if (typeof next != 'object' || typeof prev != 'object') {
 70             return {};
 71         }
 72         for (var i in next) {
 73             if (next.hasOwnProperty(i)) {
 74                 prev[i] = next[i];
 75             }
 76         }
 77         return prev;
 78     }
 79 
 80     function Subscriber(fn, options, context) {
 81         if (!this instanceof Subscriber) {
 82             return new Subscriber(fn, options, context);
 83         } else {
 84             this.id = getID();
 85             this.fn = fn;
 86             this.options = extend(this.options, options);
 87             this.context = context;
 88             this.topic = null;
 89         }
 90     }
 91 
 92     function Topic(namespace) {
 93         if (!this instanceof Topic) {
 94             return new Topic(namespace);
 95         } else {
 96             this.namespace = namespace || '';
 97             this._callbacks = [];
 98             this._topics = {};
 99             this.stoped = false;
100         }
101     }
102 
103     Topic.prototype = {
104         addSubscriber: function(fn, options, context) {
105             var callback = new Subscriber(fn, options, context);
106             this._callbacks.push(callback);
107             callback.topic = this;
108             return callback.id;
109         },
110         removeSubscriber: function(id) {
111             if (!id) {
112                 this._callbacks = [];
113 
114                 for (var x in this._topics) {
115                     if (this._topics.hasOwnProperty(x)) {
116                         this._topics[x].removeSubscriber(id);
117                     }
118                 }
119             }
120 
121             for (var y = 0, l = this._callbacks.length; y < l; y++) {
122                 if (this._callbacks[y].id == id || this._callbacks[y].fn == id) {
123                     this._callbacks[y].topic = null;
124                     this._callbacks.splice(y, 1);
125                     y--;
126                     l--;
127                 }
128             }
129         },
130         stopPropagation: function(){
131             this.stoped = true;
132         },
133         getSubscriber: function(id) {
134             for (var x = 0, l = this._callbacks.length; x < l; x++) {
135                 var callback = this._callbacks[x];
136                 if (callback.id == id || callback.fn == id) {
137                     return callback;
138                 }
139             }
140 
141             for (var y in this._topics) {
142                 if (this._topics.hasOwnProperty(y)) {
143                     var sub = this._topics[y].getSubscriber(id);
144                     if (sub != undefined) {
145                         return sub;
146                     }
147                 }
148             }
149         },
150         addTopic: function(topic) {
151             this._topics[topic] = new Topic((this.namespace?this.namespace+':' : '') + topic);
152             return this._topics[topic];
153         },
154         hasTopic: function(topic) {
155             return this._topics.hasOwnProperty(topic);
156         },
157         getTopic: function(topic) {
158             return this._topics[topic];
159         },
160         publish: function(data) {
161             console.log('Published By: '+this.namespace);
162 
163             for (var x = 0, l = this._callbacks.length; x < l; x++) {
164                 var callback = this._callbacks[x];
165                 var len;
166 
167                 callback.fn.apply(callback.context, data);
168 
169                 if (this._callbacks.length < l) {
170                     x--;
171                     l = this._callbacks.length;
172                 }
173             }
174 
175             for (var y in this._topics) {
176                 if (!this.stoped) {
177                     if (this._topics.hasOwnProperty(y)) {
178                         this._topics[y].publish(data);
179                     }
180                 }
181             }
182 
183             this.stoped = false;
184         }
185     }
186 
187     Mediator.prototype.Subscriber = Subscriber;
188     Mediator.prototype.Topic = Topic;
189 
190     return Mediator;
191 });

index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
 5     <script type="text/javascript" src="./Mediator.js"></script>
 6 </head>
 7 <body>
 8 
 9 <script type="text/javascript">
10 
11     Mediator.subscribe('new', function(data) {
12         console.log(data);
13         console.log('subscrib something. ---msg');
14     }, {}, this);
15 
16     setTimeout(function() {
17         Mediator.publish('new', 'text');
18     }, 500);
19 
20 
21     console.log('------------divider-----------');
22 
23     Mediator.subscribe('user:new', function(name, age) {
24         console.log('name:'+name+', age:'+age);
25     }, {}, this);
26 
27     Mediator.subscribe('user:new', function(name, age) {
28         console.log('Log : Save a new User.');
29     }, {}, this);
30 
31     Mediator.publish('user:new', 'Dong', '25');
32 
33     console.log('------------divider-----------');
34 
35     console.log(Mediator.getTopic('user:new'));
36 
37 </script>
38 
39 </body>
40 </html>
原文地址:https://www.cnblogs.com/dong93/p/5440347.html