var Event = (function() {
var global = this,
Event,
_default = 'default'; Event = function() {
var _create,
_listen,
_trigger,
_remove,
_shift = Array.prototype.shift,
_unshift = Array.prototype.unshift,
namespaceCache = {},
each = function(ary, fn) {
var ret;
for (var i = 0, l = ary.length; i < l; i ++) {
var n = ary[i];
ret = fn.call(n, i, n);
};
return ret;
}; _listen = function(key, fn, cache) {
if (!cache[key]) {
cache[key] = [];
};
cache[key].push(fn);
}; _trigger = function() {
var cache = _shift.call(arguments),
key = _shift.call(arguments),
args = arguments,
_self = this,
stack = cache[key]; if (!stack || !stack.length) return; return each(stack, function() {
return this.apply(_self, args);
});
}; _remove = 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] = [];
};
};
}; _create = function(namespace) {
var namespace = namespace || _default;
var cache = {},
offlineStack = [],
ret = { listen: function(key, fn, last) {
_listen(key, fn, cache);
if (offlineStack === null) return;
if (last === 'last') {
offlineStack.length && offlineStack.pop()();
} else {
each(offlineStack, function() {
this();
});
};
offlineStack = null;
}, trigger: function() {
var fn, args,
_self = this;
_unshift.call(arguments, cache);
args = arguments;
fn = function() {
return _trigger.apply(_self, args);
};
if (offlineStack) {
return offlineStack.push(fn);
};
return fn();
}, remove: function(key, fn) {
_remove(key, cache, fn);
}, one: function(key, fn, last) {
_remove(key, cache);
this.listen(key, fn, last);
} };
return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
}; return { create: _create, one: function(key, fn, last) {
var event = this.create();
event.one(key, fn, last);
}, remove: function(key, fn) {
var event = this.create();
event.remove(key, fn);
}, listen: function(key, fn, last) {
var event = this.create();
event.listen(key, fn, last);
}, trigger: function() {
var event = this.create();
event.trigger.apply(this, arguments);
}
}; }(); return Event;
})();

使用姿势:

        /*// 先发布后订阅
event.trigger('evt1', 1, 2);
event.trigger('evt1', 3, 4); // 都存到offlineStack中去了 event.listen('evt1', e1); // 当有listen监听时,遍历offlineStack中的方法,发给第一次的listen
event.listen('evt1', e2);*/ /*// 先订阅后发布
event.listen('evt1', e1);
event.listen('evt1', e2); // 先订阅的事件都存到cache对象中去了 event.trigger('evt1', 1, 2); // 每次发布,都会遍历cache对象中对象事件名的数组
event.trigger('evt1', 3, 4); */ /*// 先发布后订阅 listen方法第三个参数可以是last,只有只会去多个trigger中的最后一个
event.trigger('evt1', 1, 2); // 1).
event.trigger('evt1', 3, 4); // 2). 都存到offlineStack中去了 event.listen('evt1', e1, 'last'); // 只会收到2).这个trigger*/ /*// 先订阅后发布再删除然后再发布,会发现evt1事件对象的cache[key]数组中少了e1函数,所以
// 再次发布只有e2执行了
event.listen('evt1', e1);
event.listen('evt1', e2); event.trigger('evt1', 1, 2);
event.remove('evt1', e1);
event.trigger('evt1', 3, 4);*/ // 订阅的再多,也只使用一个订阅
/*// 1). 先订阅后发布
event.one('evt1', e1);
event.one('evt1', e2); // 会使用这个,因为前一个被删了 event.trigger('evt1', 11, 22); // 所以会执行两次e2函数
event.trigger('evt1', 33, 44);*/ // 2). 先发布后订阅
/*event.trigger('evt1', 11, 22); // 所以会执行两次e2函数
event.trigger('evt1', 33, 44); event.one('evt1', e1); // 会使用这个,因为offlineStack被置为null了
event.one('evt1', e2); // 这个不执行了,需要等到下次trigger才会触发,因为e1从cache中删掉了,加入了e2, 如果后面还有one方法以此类推,会删除上一个监听的函数,添加新的监听函数*/ // 3). 先发布后订阅 one方法的第三个参数last会只接收最后一个trigger
event.trigger('evt1', 11, 22);
event.trigger('evt1', 33, 44); event.one('evt1', e2, 'last');
event.one('evt1', e1, 'last');

JavaScript设计模式 - 订阅发布模式(观察者模式)的更多相关文章

  1. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  2. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  3. 学习javascript设计模式之发布-订阅(观察者)模式

    1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...

  4. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  5. Java里观察者模式(订阅发布模式)

    创建主题(Subject)接口 创建订阅者(Observer)接口 实现主题 实现观察者 测试 总结 在公司开发项目,如果碰到一些在特定条件下触发某些逻辑操作的功能的实现基本上都是用的定时器 比如用户 ...

  6. AngularJS的简单订阅发布模式例子

    控制器之间的交互方式广播 broadcast, 发射 emit 事件 类似于 js中的事件 , 可以自己定义事件 向上传递直到 document 在AngularJs中 向上传递直到 rootScop ...

  7. Publisher/Subscriber 订阅-发布模式

    Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WC ...

  8. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  9. RabbitMQ下的生产消费者模式与订阅发布模式

    所谓模式,就是在某种场景下,一类问题及其解决方案的总结归纳.生产消费者模式与订阅发布模式是使用消息中间件时常用的两种模式,用于功能解耦和分布式系统间的消息通信,以下面两种场景为例: 数据接入   假设 ...

随机推荐

  1. js判断数据类型的四种方法

    1.typeof typeof是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型.返回的结果用该类型的字符串(全小写字母)形式表示,包括number,string,boolean,und ...

  2. JS模拟实现数组的map方法

    昨天使用map方法的时候,突然感觉一直在直接用,也没有试试是怎么实现的,本来想直接搜一篇文章盘一下子,结果没搜到合适的,好吧,那就自己来写一下子吧 今天就来实现一个简单的map方法 首先我们来看一下m ...

  3. Java抽象类和接口的比较

    一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架,当代表业务逻辑的高层抽象层结构 合理时,你底层的具体实现需要考虑的就仅仅是一些算法和一些具体 ...

  4. Sharepoint 2013 Gatherer 数据库的架构版本低于此 Gatherer 应用程序支持的向后兼容的最低架构版本

    管理中心 ->升级和迁移 ->查看数据库状态 解决方法: 开始-运行(以管理员身份运行),输入如下命令. cd  C:\Program Files\Common Files\Microso ...

  5. 启动MySQL报错

    安装完MySQL,启动MySQL报错,报错信息如下:Starting MySQL....The server quit without updating PID file (/data/mysqlda ...

  6. 浅谈C#依赖注入

    什么是依赖注入?不管是js中的一些前端框架还是,java,C#,php等中的一些后端开发框架中,都会涉及这个看着逼格略高的词语:依赖注入,越是看着好像很厉害的东西越是会让许多人学习产生恐惧,好像很厉害 ...

  7. Pyhon环境变量的一些坑

    在正常的情况下,使用编译器执行Python文件,无需考虑环境变量的改变 例:sum --one --one1.py --two --two1.py 在执行one.py文件需要调用 two.py中某个方 ...

  8. TinyEditor

    今天在github 上看到一个非常巧妙的项目:umpox/TinyEditor 使用简单的浏览器就能构造一个简单的实时运行代码的基于浏览器的前端编辑器,只需要很少代码: 使用方法: 粘贴如下代码到浏览 ...

  9. if条件简单语法

    if语句是实际工作中最重要最常用的语句. if条件语法: 单分支结构 if [ 条件 ] then 指令 fi 或 if [ 条件 ]:then 指令 fi if 单分支条件中文编程形象语法: 如果 ...

  10. python3 下列表与字典转换

    在写爬虫的时候,经常需要处理cookie,requests库里的cookie是dict,但是headers['cookie']却是一个key=value的字符串. 下面是几个用推导式实现的转换函数,供 ...