观察者模式

1. 介绍

  • 发布者与订阅者是多对多的方式
  • 通过推与拉获取数据:发布者推送到订阅者或订阅者到发布者那边拉
  • 使并行开发的多个实现能彼此独立地进行修改
  • 其实我们在前端开发中使用到的时间监听就是浏览器实现的观察者模式

2. 示例:订阅报纸

function Publisher() {
this.subscribers = [];
}
Publisher.prototype.deliver = function(data) {
this.subscribers.forEach(function(fn) {
fn(data)
})
return this;
} Function.prototype.subscribe = function(publisher) {
var that = this;
var aleradyExists = publisher.subscribers.some(function(el) {
return el === that;
});
if(!aleradyExists) {
publisher.subscribers.push(this);
}
return this;
} Function.prototype.unsubscribe = function(publisher) {
var that = this;
publisher.subscribers = publisher.subscribers.filter(function(el) {
return el !== that;
})
return this
} var NewYoukTimes = new Publisher;
var SfChronicle = new Publisher; var Joe = function(from) {
console.log('Delivery from ' + from + ' to Joe')
} var Same = function(from) {
console.log('Delivery from ' + from + ' to Same')
} // usage // 订阅
Joe.subscribe(NewYoukTimes).subscribe(SfChronicle)
Same.subscribe(NewYoukTimes) // 发布
NewYoukTimes.deliver('aa').deliver('cc')
SfChronicle.deliver('dd') // 取消订阅
Joe.unsubscribe(NewYoukTimes)

3. 示例:动画

里面有个 Animation 类提供了三个可以被订阅的观察对象 onStart、onComplete、onTween,有点类似于浏览器提供的事件监听,只是浏览器提供的是 onclick、onchange 等。由 Animation 内部决定这三个观察对象什么时候发布信息,其他的订阅者只要等待被触发就行。

<style>
#img {
margin-top: 20px;
}
</style> <body>
<button id="startBt">开始</button>
<button id="stopBt">停止</button>
<br/>
<img id="img" src="./images/fly1.png">
</body> <script>
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn
return this
} function Publisher() {
this.subscribers = [];
}
Publisher.prototype.deliver = function(data) {
this.subscribers.forEach(function(fn) {
fn(data)
})
return this;
} Function.prototype.subscribe = function(publisher) {
var that = this;
var aleradyExists = publisher.subscribers.some(function(el) {
return el === that;
});
if(!aleradyExists) {
publisher.subscribers.push(this);
}
return this;
} Function.prototype.unsubscribe = function(publisher) {
var that = this;
publisher.subscribers = publisher.subscribers.filter(function(el) {
return el !== that;
})
return this
} var Animation = function(o) {
this.config = o
this.onStart = new Publisher // 可观察对象
this.onComplete = new Publisher // 可观察对象
this.onTween = new Publisher // 可观察对象
this.timer = undefined;
this.frame = 1;
this.state = 'stop'
};
Animation.method('start', function(){
if(this.state !== 'stop') {
return
}
this.state = 'start'
this.onComplete.deliver('start at: ' + new Date().getTime())
var that = this
this.timer = setInterval(function(){
that.onTween.deliver(that.frame)
that.frame++;
},this.config.timeLate);
}).method('stop', function() {
if(this.state !== 'start') {
return
}
this.state = 'stop'
clearInterval(this.timer);
// this.frame = 1;
this.onComplete.deliver('stop at: ' + new Date().getTime())
}) var animation = new Animation({ timeLate: 400}) // 超人飞行部分动画
var frameImg = document.getElementById('img')
var jumpToFly = function(info) { // 订阅者
console.log(info)
}
var superManFlying = function(i) {
var frame = i%3 + 1;
frameImg.src = "./images/fly" + frame + ".png"
console.log('frame: ' + i) // 订阅者
};
var downToLand = function(info) { // 订阅者
console.log(info)
}
jumpToFly.subscribe(animation.onStart)
superManFlying.subscribe(animation.onTween)
downToLand.subscribe(animation.onComplete) document.getElementById('startBt').addEventListener('click', function() {
animation.start();
})
document.getElementById('stopBt').addEventListener('click', function() {
animation.stop()
}) </script>

4. 观察者的适用场合

  • 希望把人的行为和应用程序的行为分开

5. 观察者模式的利与弊

  • 利:

    • 在基于行为的大型应用程序中,可能会连续的发生几十、几百、几千次各种事件,通过观察者模式可以削减为事件注册注册监听器的次数,让可观察对象借助一个事件监听器替你处理各种行为并将信息委托给他的订阅者,从而减低内存消耗和互动性能,这样有利于减少系统开销并提高程序的可维护性
  • 弊:
    • 创建可观察对象所带来的加载事件开销(可以通过惰性加载技术化解,具体而言就是把新的可观察对象的实例化推迟到需要发送事件通知的时候,这样一来,订阅者在事件尚未创建的时候就能订阅他,而程序的初始化时间也就不收影响)

注意

转载、引用,但请标明作者和原文地址

JavaScript设计模式(10)-观察者模式的更多相关文章

  1. JavaScript设计模式之观察者模式(学习笔记)

    设计模式(Design Pattern)对于软件开发来说其重要性不言而喻,代码可复用.可维护.可扩展一直都是软件工程中的追求!对于我一个学javascript的人来说,理解设计模式似乎有些困难,对仅切 ...

  2. 再起航,我的学习笔记之JavaScript设计模式18(观察者模式)

    观察者模式 观察者模式(Observer): 又被称为发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合. 创建一个观察者对象 首先我们创建一个闭包对象,让其在页面加 ...

  3. 再起航,我的学习笔记之JavaScript设计模式10(单例模式)

    单例模式 单例模式(Singleton) : 又被称为单体模式,是只允许实例化一次的对象类.一个类有且仅有一个实例,并且自行实例化向整个系统提供. 命名空间 单例模式可能是JavaScript中我们最 ...

  4. JavaScript设计模式-22.观察者模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. javascript设计模式之观察者模式

    观察者模式又称发布/订阅模式   publish/subscribe 它是一种一对多的关系,让多个观察者对象同时监听某一主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得他们能够自动 ...

  6. javascript 设计模式之观察者模式

    观察者模式又叫发布——订阅模式,顾名思义pub——sub就是被动触发的,:不要给我......,我会给你.......就是一个发布订阅的解释,实质就是对程序中的某个对象状态进行监听观察,并且在该对象发 ...

  7. JavaScript设计模式-10.工厂模式实例xhr

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. JavaScript设计模式与开发实践 - 观察者模式

    概述 观察者模式又叫发布 - 订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个目标对象(为了方便理解,以下将观察者对象叫做订阅者,将目标对象叫做 ...

  9. javaScript 设计模式系列之一:观察者模式

    介绍 观察者模式又叫发布订阅模式(Publish/Subscribe),一个目标对象管理所有相依于它的观察者对象.该模式中存在两个角色:观察者和被观察者.目标对象与观察者之间的抽象耦合关系能够单独扩展 ...

随机推荐

  1. BZOJ 3143: [Hnoi2013]游走 [概率DP 高斯消元]

    一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...

  2. FileBeat安装配置

    在ELK中因为logstash是在jvm上跑的,资源消耗比较大,对机器的要求比较高.而Filebeat是一个轻量级的logstash-forwarder,在服务器上安装后,Filebeat可以监控日志 ...

  3. 【IT人】如何提高阅读源代码的效率

    1.最近刚到公司,公司就发一架构代码自己看,看了几天看的想吐,也在网上找了下相关的技巧吧,不是有句话叫做:成功必有方法,失败总是借口! 2.借鉴别人的方法来看看如下: 记得在开源流行之前,我看过的代码 ...

  4. 重写equals()和hashCode()

    什么时候需要重写equals()? 只有当一个实例等于它本身的时候,equals()才会返回true值.通俗地说,此时比较的是两个引用是否指向内存中的同一个对象,也可以称做是否实例相 等.而我们在使用 ...

  5. 使用Nginx实现灰度发布

    灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B ...

  6. NOI2009 二叉查找树 【区间dp】

    [NOI2009]二叉查找树 [问题描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左子树结点的数据值大,而比它右子树结点的数据值小.另一方面,这棵查找树中每个结点都有 ...

  7. linux、windows系统间传输文件

    日常工作中经常涉及到系统间的文件传输,下面就简单说一下常用的方法   linux--windows      工具:winscp.SecureCRT.Zmodem(sz, rz)   linux--l ...

  8. C#委托与事件--简单笔记

    委托 简单记录点东西 适合似懂非懂的朋友看看 委托类型用来定义和响应应用程序中的回调. 借此可以设计各种有面向对象特性的代码模式.下面要说的事件在我看来就是委托的一种实现,再深一步讲,利用委托加事件, ...

  9. java-redis列表数据操作示例(二)

    接上篇博文<java-redis字符类数据操作示例(一)>,redis连接管理类的代码请跳转查看. 一.列表类型缓存测试类 public class ListTest { /** * 主测 ...

  10. Spring-Security 自定义Filter完成验证码校验

    Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...