javaScript 设计模式系列之一:观察者模式
介绍
观察者模式又叫发布订阅模式(Publish/Subscribe),一个目标对象管理所有相依于它的观察者对象。该模式中存在两个角色:观察者和被观察者。目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
该模式通常有两种实现策略:"推"(push) 和 "拉"(pull)
例:对于报社可能雇佣投送人员四处送报给订阅者,这就是主动推送。而对于规模小的报社没有足够的资源去雇佣投送员,这时候可以采取 "拉" 的方式。就是在订阅者附近提供自己的数据,供订阅者 "拉" 自己所需的数据。
实现
push
var Observable = {
observers: []
, lastId: -1
, addObserver: function(observer) {
this.observers.push({
callback: observer
, id: ++this.lastId
})
return this.lastId
}
, removeObserver: function(id) {
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i]
if (this.observers[i].id == id) {
this.observers.splice(i, 1)
return true
}
}
return false
}
, notifyObservers: function(message) {
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i].callback(message)
};
}
}
var id_1 = Observable.addObserver(function(message){
console.log("First observer message:" + message)
})
var observer = function(message){
console.log("Second observer message:" + message)
}
var id_2 = Observable.addObserver(observer)
Observable.notifyObservers('test 1')
Observable.removeObserver(id_2)
Observable.notifyObservers('test 2')
pull
var Observable = {}
;(function(O){
var observers = []
, privateVar
O.addObserver = function(observer) {
observers.push(observer)
}
O.removeObserver = function(observer) {
var index = observers.indexOf(observer)
if (~index) {
observers.splice(index, 1)
}
}
O.notifyObservers = function() {
for (var i = observers.length - 1; i >= 0; i--) {
observers[i].update()
};
}
O.updatePrivate = function(newValue) {
privateVar = newValue
this.notifyObservers()
}
O.getPrivate = function() {
return privateVar
}
}(Observable))
Observable.addObserver({
update: function(){
this.process()
}
, process: function(){
var value = Observable.getPrivate()
console.log("Private value is: " + value)
}
})
Observable.updatePrivate('test 1')
// Private value is: test 1
Observable.updatePrivate('test 2')
// Private value is: test 2
被观察对象将通知所有的观察者,并且每个观察者将从被观察对象中提取所需的信息。
让多个对象都具有观察者发布订阅的功能
var observer = {
addSubscriber:function (callback) {
this.subscribers[this.subscribers.length] = callback;
},
removeSubscriber:function (callback) {
for (var i = 0; i < this.subscribers.length; i++) {
if (this.subscribers[i] === callback) {
delete(this.subscribers[i]);
}
}
},
publish:function (what) {
for (var i = 0; i < this.subscribers.length; i++) {
if (typeof this.subscribers[i] === 'function') {
this.subscribers[i](what);
}
}
},
make:function (o) { // turns an object into a publisher
for (var i in this) {
o[i] = this[i];
o.subscribers = [];
}
}
};
var blogger = {
writeBlogPost:function () {
var content = 'Today is ' + new Date();
this.publish(content);
}
};
var la_times = {
newIssue:function () {
var paper = 'Martians have landed on Earth!';
this.publish(paper);
}
};
observer.make(blogger);
observer.make(la_times);
var jack = {
read:function (what) {
console.log('I just read that ' + what)
}
};
var jill = {
gossip:function (what) {
console.log('You didn\'t hear it from me, but ' + what)
}
};
blogger.addSubscriber(jack.read);
blogger.addSubscriber(jill.gossip);
blogger.writeBlogPost();
blogger.removeSubscriber(jill.gossip);
blogger.writeBlogPost();
la_times.addSubscriber(jill.gossip);
la_times.newIssue();
避免创建多个被观察者对象,可以增加 "命名空间"
var Observable = {
observers: []
, addObserver: function(topic, observer) {
this.observers[topic] || (this.observers[topic] = [])
this.observers[topic].push(observer)
}
, removeObserver: function(topic, observer) {
if (!this.observers[topic])
return;
var index = this.observers[topic].indexOf(observer)
if (~index) {
this.observers[topic].splice(index, 1)
}
}
, notifyObservers: function(topic, message) {
if (!this.observers[topic])
return;
for (var i = this.observers[topic].length - 1; i >= 0; i--) {
this.observers[topic][i](message)
};
}
}
Observable.addObserver('cart', function(message){
console.log("First observer message:" + message)
})
Observable.addObserver('notificatons', function(message){
console.log("Second observer message:" + message)
})
Observable.notifyObservers('cart', 'test 1')
// First observer message:test 1
Observable.notifyObservers('notificatons', 'test 2')
// Second observer message:test 2
相关阅读
javascript-observer-publish-subscribe-pattern
深入理解JavaScript系列(32):设计模式之观察者模式
javascript-patterns-observer
javaScript 设计模式系列之一:观察者模式的更多相关文章
- javascript设计模式系列
javascript设计模式系列 创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式( ...
- 【JavaScript设计模式系列---开篇预览】
转:http://www.cnblogs.com/Darren_code/archive/2011/08/31/JavascripDesignPatterns.html 2011-08-31 23:5 ...
- Javascript设计模式系列三
继承,一个类或对象继承另一个类或对象的三种方法.类式继承.原型式继承.掺元类. 一.类式继承,原型链.Extend函数. <script type="text/javascript&q ...
- Javascript设计模式系列二
创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用th ...
- Javascript设计模式系列一
定义类,方法赋值给prototype属性各种写法: 方法一: <script type="text/javascript"> ////定义Message类 var Me ...
- 【读书笔记】读《JavaScript设计模式》之观察者模式
一.定义 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象 ...
- 设计模式系列之观察者模式(Observer Pattern)
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作 ...
- [转] 浅析JavaScript设计模式——发布-订阅/观察者模式
前一段时间一直在写CSS3的文章 一直都没写设计模式 今天来写写大名鼎鼎观察者模式 先画张图 观察者模式的理解 我觉得还是发布-订阅模式的叫法更容易我们理解 (不过也有的书上认为它们是两种模式……) ...
- C#设计模式系列:观察者模式(Observer)
在软件构建过程中,需要为某些对象建立一种“通知依赖关系”,即一个对象的状态发生改变,所有的依赖对象都需要得到通知. 1.观察者模式简介 1.1>.定义 定义对象间的一种一对多的依赖关系,当一个对 ...
随机推荐
- socket bind详解
http://www.cnblogs.com/nightwatcher/archive/2011/07/03/2096717.html 在最开始接触bind的时候,只是在写基于tcp的server端的 ...
- JQ实战一之烟花
本次的效果大概为当用户点击网页时,网页下方弹出一个类似烟花的长条条,然后在桌面上散开以达成类似烟花的特效.话不多说先上图. 首先布局,布局很简单 <style> body { backgr ...
- 看Lucene源码必须知道的基本规则和算法
上中学的时候写作文,最喜欢的季节我都是写冬天.虽然是因为写冬天的人比较少,那时确实也是对其他季节没有什么特殊的偏好,反而一到冬天,自己皮肤会变得特别白.但是冬天啊,看到的只有四季常青盆栽:瓜栗(就是发 ...
- JavaScript高级内容:原型链、继承、执行上下文、作用域链、闭包
了解这些问题,我先一步步来看,先从基础说起,然后引出这些概念. 本文只用实例验证结果,并做简要说明,给大家增加些印象,因为单独一项拿出来都需要大篇幅讲解. 1.值类型 & 引用类型 funct ...
- NPOI操作类
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Secu ...
- 学习vue 20天,我写了点东西
往昔 最初团队里使用Angularjs进行开发,刚开始还好,到了项目后期越发感觉Angularjs太重了,以至于后来重构项目时,毅然放弃Angularjs,投入了Vue的怀抱.除了组建团队时,是我搭建 ...
- 【Windows 10 应用开发】输入模拟
---恢复内容开始--- Input Injection 直译为:输入注入.通俗的译法为:模拟输入.此注入行为可以模拟以下几种输入行为: 1.键盘按键. 2.鼠标. 3.触控. 4.书写笔输入. 5. ...
- Docker for Mac与IntelliJ Docker Integration插件的兼容性问题
笔者在自己的Mac上安装的是Docker for Mac,而不是Docker Toolbox. 这两者最主要的区别在于Docker for Mac用HyperKit作为虚拟化解决方案而不是Virtua ...
- js日期转化(计算一周的日期)
之前做项目的时候遇到过一个日期转化的问题,一个日期控件和近一天,近七天和近一月的的联动效果.发现自己不会,后来就百度了一下解决了这个问题. 现在抽空又写了一个时间转化的案例(计算一周的日期),因为之前 ...
- 工资不高也要给自己放假 这几款APP估计你用得上
我是这样的一个人,我宁愿工资不高,只要给我足够的假期,那我就满足了.都说上班就是为了赚钱,但如果身体不好,赚再多的钱也是无福享受,所以建议各位,有机会的话,一定要抽出时间去旅游,去放松. 现在我们外出 ...