自定义事件机制——观察者模式
2013-04-17 20:14
239 查看
观察者模式是对应用系统进行抽象的有力手段。你可以定义一些事件供其他开发人员使用,而并不需要为此深入了解他们的代码。一个事件可以被多个订阅者订阅,而一个订阅者也可以订阅多个不同的事件。对于浏览器这类互动环境来说这非常理想。现在的Web应用程序越来越大,在此背景下,作为一种提高代码的可维护性和简洁性的有力手段,可观察对象的作用更显突出。这种模式的应用有助于防止第三方开发人员和合作伙伴因为对你的应用程序的细节了解得太多而把事情搞糟。提高程的高度解耦有助于程序代码的维护工作。
下面是基于javascript的观察者模式:
有两种用法:
第一种用法,创建Events对象实例:
当然也可以移除事件监听:// 移除所有监听
当然也可以同时触发多个事件监听:
第二种用法,继承Events事件,Events的create方法:
上面创建了一个Paper类,同时继承了Events事件机制。
当然也可以先创建Paper类,然后再继承Events事件机制
下面是一个综合性的实例:
下面是基于javascript的观察者模式:
var Events = (function (W) { var slice = Array.prototype.slice hasOwen = Object.prototype.hasOwnProperty; function emperty(o) { for (var k in o) { return false; } return true; } if (!String.prototype.trim){ String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/) } } var Events = function () { }; // 发布方法 Events.prototype.fire = function (types) { var len = arguments.length, events=this._events||(this._events={}), _fn, args = []; if (emperty(events)) { return this; } // 无参数触发全部监听 if (len == 0) { types = events; } else if (typeof types == 'string') { types = types.split(/\s+/); args = slice.call(arguments, 1); } for (var type in types) { if (typeof(types.length)=='number'){ type = types[type] } fns = (events[type] || []).slice(); if (fns.length == 0) { continue; } for (; _fn = fns.shift();) { _fn.apply(null, args); } } return this; }; //订阅方法 Events.prototype.on = function (types, fn) { var type, fns, events = this._events||(this._events={}); if (!types||!fn||typeof types != 'string') { return this; } for (types = types.split(/\s+/); type = types.shift();) { fns = events[type] || (events[type] = []); fns.push(fn) } return this; }; //退订方法 Events.prototype.off = function (types, fn) { var type, fns, events = this._events, len = arguments.length, flen; if (len == 0) { this._events = {}; return this; } for (types = types.split(/\s+/); type = types.shift();) { if (!events[type]) { continue; } if (len == 1) { delete events[type]; continue; } fns = events[type]; flen = fns.length; for (; flen--;) { if (fns[flen] == fn) { fns.splice(flen, 1); } } } return this; }; Events.create = function(o){ var to = o.prototype || o; var from = Events.prototype; for (var key in from){ if (hasOwen.call(from,key)){ to[key] = from[key]; } } return o; } return Events; }(window));
有两种用法:
第一种用法,创建Events对象实例:
// 创建事件监听器 var ev = new Events(); var fn1 = function(){ console.log('the first example!'); } var fn2 = function(){ console.log('the two example!'); } // 注册事件 ev.on('example',fn1); // 同时注册多个监听 ev.on('example2 example3 example4',fn2); // 当然也可以同时监听同一件事件 ev.on('example5',fn1); // 注册匿名函数 ev.on('example_1',function(){ console.log('the first example_1') }) // 触发监听 ev.fire();
当然也可以移除事件监听:// 移除所有监听
ev.off(); // 移除多个监听 //ev.off('example example2'); // 移除所有单个监听 //ev.off('example3'); // 移除某个监听的指定事件 // ev.off('example5',fn1)
当然也可以同时触发多个事件监听:
// 触发有监听 ev.fire('example'); // 触发所有监听 ev.fire(); // 触发多个监听 ev.fire('example2 example3 example4');
第二种用法,继承Events事件,Events的create方法:
var Paper = Events.create(function(name, pages, price) { this.name = name; this.pages = pages; this.price = price; });
上面创建了一个Paper类,同时继承了Events事件机制。
当然也可以先创建Paper类,然后再继承Events事件机制
var Paper = function(name, pages, price) { this.name = name; this.pages = pages; this.price = price; }; Events.create(Paper); // 还可以 Events.create(Paper.prototype);
下面是一个综合性的实例:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
</head>
<body>
<button id="sendWeekly">发送周报</button>
<button id="sendDaily">发送日报</button>
<script>
var Events = (function (W) { var slice = Array.prototype.slice hasOwen = Object.prototype.hasOwnProperty; function emperty(o) { for (var k in o) { return false; } return true; } if (!String.prototype.trim){ String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/) } } var Events = function () { }; // 发布方法 Events.prototype.fire = function (types) { var len = arguments.length, events=this._events||(this._events={}), _fn, args = []; if (emperty(events)) { return this; } // 无参数触发全部监听 if (len == 0) { types = events; } else if (typeof types == 'string') { types = types.split(/\s+/); args = slice.call(arguments, 1); } for (var type in types) { if (typeof(types.length)=='number'){ type = types[type] } fns = (events[type] || []).slice(); if (fns.length == 0) { continue; } for (; _fn = fns.shift();) { _fn.apply(null, args); } } return this; }; //订阅方法 Events.prototype.on = function (types, fn) { var type, fns, events = this._events||(this._events={}); if (!types||!fn||typeof types != 'string') { return this; } for (types = types.split(/\s+/); type = types.shift();) { fns = events[type] || (events[type] = []); fns.push(fn) } return this; }; //退订方法 Events.prototype.off = function (types, fn) { var type, fns, events = this._events, len = arguments.length, flen; if (len == 0) { this._events = {}; return this; } for (types = types.split(/\s+/); type = types.shift();) { if (!events[type]) { continue; } if (len == 1) { delete events[type]; continue; } fns = events[type]; flen = fns.length; for (; flen--;) { if (fns[flen] == fn) { fns.splice(flen, 1); } } } return this; }; Events.create = function(o){ var to = o.prototype || o; var from = Events.prototype; for (var key in from){ if (hasOwen.call(from,key)){ to[key] = from[key]; } } return o; } return Events; }(window));
var Paper = Events.create(function(name, pages, price) { this.name = name; this.pages = pages; this.price = price; });
Paper.prototype.send = function (types) {
this.fire(types, {
name:this.name,
pages:this.pages,
price:this.price
});
};
function Person(name) {
var that = this;
this.name = name;
this.recive = function (paper) {
console.log(that.name + ' recive Pager detail:\n' + 'name:' + paper.name + '\npages:' + paper.pages + '\nprice:' + paper.price)
}
}
var person = new Person('Lucy'),
person1 = new Person('Tom');
var Weekly = new Paper('weekly', 298, '$6'),
Daily = new Paper('daily', 7, '$0.8');
Weekly.on('weekly', person.recive),
Weekly.on('weekly', person1.recive);
Daily.on('daily', person.recive);
Weekly.off('weekly',person1.recive)
var $ = function (id) {
return document.getElementById(id);
}
$('sendWeekly').onclick = function () {
Weekly.send('weekly');
}
$('sendDaily').onclick = function () {
Daily.send('daily');
}
</script>
</body>
</html>
相关文章推荐
- java事件处理机制(自定义事件)/观察者模式
- 使用javascript模拟观察者模式和事件监听广播机制
- 观察者模式与RegistrantList机制
- [架构]事件机制--典型观察者模式
- 谈谈JS的观察者模式(自定义事件)
- UI与逻辑的关系、主线程与工作线程的通讯及对观察者模式、消息总线机制的思考
- 关于iphone开发中观察者模式中的kvo机制的总结
- 谈KVC、KVO(重点观察者模式)机制编程
- 当观察者模式和回调机制遇上Android源码
- 谈谈JS的观察者模式(自定义事件)
- 自定义事件(观察者模式)
- Cocos中的观察者设计模式与通知机制
- 观察者设计模式实现缓存机制
- 详解java的事件监听机制和观察者设计模式
- 事件机制和观察者模式
- java设计模式-观察者模式(广播机制,消息订阅)
- Cocos中的观察者设计模式与通知机制
- 观察者模式-Java自定义事件 推荐
- libjingle中的signal/slot机制和观察者模式
- java:从消息机制谈到观察者模式