Skip to content

Instantly share code, notes, and snippets.

@zD98
Last active March 17, 2016 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zD98/47df6a43c642a85e6392 to your computer and use it in GitHub Desktop.
Save zD98/47df6a43c642a85e6392 to your computer and use it in GitHub Desktop.
设计模式-mediator-复杂实现
//Mediator
(function(root){
//生成特定callback ID, 利于检索
function guidGenerator() {}
//订阅者
function Subscriber(fn, options, context) {
if(!this instanceof Subscriber){
return new Subscriber(fn, options, context);
}else{
this.id = guidGenerator();
this.fn = fn;
this.options = options;
this.context = context;
this.topic = null;
}
}
//Topic 包含子topic
function Topic (namespace) {
if(!this instanceof Topic){
return new Topic(namespace);
}else {
this.namespace = namespace;
//Topic的回调函数数组, [Subscriber]
this._callbacks = [];
//子topic 列表
this._topics = {};
//在递归查询时阻止重复递归
this.stopped = false;
}
}
Topic.prototype = {
// 为Topic 添加Subscriber
AddSubscriber : function (fn, options, context){
var callback = new Subscriber(fn, options, context);
this._callbacks.push(callback);
callback.topic = this;
return callback
},
StopPropagation:function() {
this.stopped = true;
},
GetSubscriber:function(identifier) {
//在本Topic的回调函数列表里寻找订阅者
for(var x = 0,y=this._callbacks.length;x<y;x++){
if(this._callbacks[x].id == identifier ||this._callbacks[x].fn == identifier){
return this._callbacks[x];
}
}
//Topic中没有该订阅者
//在子topic中递归寻找订阅者
for(var z in this._topics){
if(this._topics.hasOwnProperty(z)){
var sub = this._topics[z].GetSubscriber(identifier);
if(sub!==undefined){
return sub;
}
}
}
},
//添加子topic
AddTopic:function(topic) {
this._topics[topic] = new Topic((this.namespace?this.namespace+":":"")+topic);
},
//检查是否有某个子topic
HasTopic:function (topic){
return this._topics[topic];
},
//返回某个子topic
returnTopic:function(topic){
return this._topics[topic];
},
//移除订阅者
removeSubscriber:function(identifier){
if(!identifier){
//清空订阅者
this._callbacks = [];
//清空子topic的订阅者
for(var z in this._topics) {
if(this._topics.hasOwnProperty(z)){
this._topics[z].removeSubscriber(identifier);
}
}
}
//删除Topic的identifer的Subscriber
for (var y=0,x = this._callbacks.length;y<x;y++){
if(this._callbacks[y].fn == identifier||this._callbacks[y].id ==identifier){
this._callbacks[y].topic = null;
this._callbacks.splice(y,1);
x--;
y--;
}
}
},
//发布事件,递归发布
Publish:function (data){
//发布给callbacks
for(var y = 0,x = this._callbacks.length;y<x;y++){
var callback = this._callbacks[y],l;
callback.fn.apply(callback.context,data);
l = this._callbacks.length;
if(l<x){
y--;
x=l;
}
}
//子topic 执行递归 发布数据
for(var x in this._topics){
if(!this.stopped){
if(this._topics.hasOwnProperty(x)){
this._topics[x].Publish(data)
}
}
}
this.stopped = false;
}
};
//用于添加Topic, Subscriber
function Mediator(){
if(!this instanceof Mediator){
return new Mediator();
}else {
this._topics = new Topic("");
}
}
Mediator.prototype = {
//允许inbox:messages:new:read命名空间
GetTopic:function(namespace){
//拆分命名空间
var topic = this._topics,namespaceHierarchy = namespace.split(":");
if(namespace===""){
return topic;
}
//对namespace 递归查找 topic
if(namespaceHierarchy.length>0){
for(var i = 0,j = namespaceHierarchy.length;i<j;i++){
if(!topic.HasTopic(namespaceHierarchy[i]) ){
//没有topiac则添加
topic.AddTopic(namespaceHierarchy[i]);
}
//进入下一级topic
topic = topic.returnTopic(namespaceHierarchy[i]);
}
}
//返回最深层topic
return topic;
},
//订阅消息
Subscribe:function(topicName, fn, options, context){
var options = options ||{},
context = context ||{},
topic = this.GetTopic(topicName),
sub = topic.AddSubscriber(fn,options,context);
return sub;
},
//
GetSubscriber :function(identifier , topic) {
return this.GetTopic(topic ||"").GetSubscriber(identifier);
},
//
Remove:function(topicName, identifier){
this.GetTopic(topicName).removeSubscriber(identifier);
},
//
Publish:function(topicName){
//获取参数列表
var args = Array.prototype.slice.callback(arguments,1),
topic = this.GetTopic(topicName);
args.push(topic);
this.GetTopic(topicName).Publish(args);
}
};
root.Mediator = Mediator;
Mediator.Topic = Topic;
Mediator.Subscriber = Subscriber;
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment