JS设计模式——观察者模式(通俗易懂)
Observer模式的概念
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
Observer模式的角色
Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
ConcreteObserver
观察者的具体实现:得到通知后将完成一些具体的业务逻辑处理。
观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的dom事件. 也是js和dom之间实现的一种观察者模式.
div.onclick = function click (){
alert ("click")
}
只要订阅了div的click事件. 当点击div的时候, function click就会被触发.
那么到底什么是观察者模式呢. 先看看生活中的观察者模式。
好莱坞有句名言. “不要给我打电话, 我会给你打电话”. 这句话就解释了一个观察者模式的来龙去脉。 其中“我”是发布者, “你”是订阅者。
再举个例子,我来公司面试的时候,完事之后每个面试官都会对我说:“请留下你的联系方式, 有消息我们会通知你”。
在这里“我”是订阅者, 面试官是发布者。所以我不用每天或者每小时都去询问面试结果, 通讯的主动权掌握在了面试官手上。而我只需要提供一个联系方式。
观察者模式可以很好的实现2个模块之间的解耦。 假如我正在一个团队里开发一个html5游戏. 当游戏开始的时候,需要加载一些图片素材。
加载好这些图片之后开始才执行游戏逻辑. 假设这是一个需要多人合作的项目. 我完成了Gamer和Map模块, 而我的同事A写了一个图片加载器loadImage.
loadImage的代码如下
loadImage(imgAry, function () {
Map.init();
Gamer.init();
})
当图片加载好之后, 再渲染地图, 执行游戏逻辑. 嗯, 这个程序运行良好. 突然有一天, 我想起应该给游戏加上声音功能. 我应该让图片加载器添上一行代码.
loadImage(imgAry, function () {
Map.init();
Gamer.init();
Sount.init();
})
可是写这个模块的同事A去了外地旅游. 于是我打电话给他, 喂. 你的loadImage函数在哪, 我能不能改一下, 改了之后有没有副作用.
如你所想, 各种不淡定的事发生了. 如果当初我们能这样写呢:
loadImage.listen("ready", function () {
Map.init();
})
loadImage.listen("ready", function () {
Gamer.init();
})
loadImage.listen("ready", function () {
Sount.init();
})
loadImage完成之后, 它根本不关心将来会发生什么, 因为它的工作已经完成了. 接下来它只要发布一个信号
loadImage.trigger( "ready" );
下面是对观察者模式的实现
/**
* 发布订阅模式(观察者模式)
* handles: 事件处理函数集合
* on: 订阅事件
* emit: 发布事件
* off: 删除事件
**/ class PubSub {
constructor() {
this.handles = {};
} // 订阅事件
on(eventType, handle) {
if (!this.handles.hasOwnProperty(eventType)) {
this.handles[eventType] = [];
}
if (typeof handle == 'function') {
this.handles[eventType].push(handle);
} else {
throw new Error('缺少回调函数');
}
return this;
} // 发布事件
emit(eventType, ...args) {
if (this.handles.hasOwnProperty(eventType)) {
this.handles[eventType].forEach((item, key, arr) => {
item.apply(null, args);
})
} else {
throw new Error(`"${eventType}"事件未注册`);
}
return this;
} // 删除事件
off(eventType, handle) {
if (!this.handles.hasOwnProperty(eventType)) {
throw new Error(`"${eventType}"事件未注册`);
} else if (typeof handle != 'function') {
throw new Error('缺少回调函数');
} else {
this.handles[eventType].forEach((item, key, arr) => {
if (item == handle) {
arr.splice(key, );
}
})
}
return this; // 实现链式操作
}
} // 下面做一些骚操作
let callback = function () {
console.log('you are so nice');
} let pubsub = new PubSub();
pubsub.on('completed', (...args) => {
console.log(args.join(' '));
}).on('completed', callback); pubsub.emit('completed', 'what', 'a', 'fucking day');
pubsub.off('completed', callback);
pubsub.emit('completed', 'fucking', 'again');
输出值:
what a fucking day
you are so nice
fucking again
JS设计模式——观察者模式(通俗易懂)的更多相关文章
- js设计模式-观察者模式
定义: 观察者模式又叫发布订阅模式,它定义了对象间的一种一对多的依赖关系.观察者模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间的互相通信. 思路 定义一个对象,在对象中实 ...
- js 设计模式——观察者模式
观察者模式 定义 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状 ...
- js设计模式——3.观察者模式
js设计模式——观察者模式 /*js设计模式——.观察者模式*/ // 主题,保存状态,状态变化之后触发所有观察者对象 class Subject { constructor() { this.sta ...
- 前端笔记之JavaScript面向对象(三)初识ES6&underscore.js&EChart.js&设计模式&贪吃蛇开发
一.ES6语法 ES6中对数组新增了几个函数:map().filter().reduce() ES5新增的forEach(). 都是一些语法糖. 1.1 forEach()遍历数组 forEach() ...
- JS设计模式(一)
刚入职时,看过一段时间的设计模式,似懂非懂.不知不觉过去七个月了,对JS的理解更深刻了,数据结构与算法的基础也基本上算是过了一遍了,接下来要把设计模式搞定,然后不再深层次研究JS了,而是学习前端自动化 ...
- 18. 星际争霸之php设计模式--观察者模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- js设计模式(12)---职责链模式
0.前言 老实讲,看设计模式真得很痛苦,一则阅读过的代码太少:二则从来或者从没意识到使用过这些东西.所以我采用了看书(<js设计模式>)和阅读博客(大叔.alloyteam.聂微东)相结合 ...
- JS设计模式——5.单体模式
JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html 单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...
- js 设计模式-接口
js模拟java接口检测函数:确保子类实现接口中的方法:(出自js设计模式) 上代码: <script type="text/javascript" > <%-- ...
随机推荐
- c# 后台绑定treeview 单个tab
<wijmo:C1TreeView ID="C1TreeView1" runat="server" ShowCheckBoxes="true&q ...
- 使用Ajax和JSON实现注册时候验证用户名是否存在的功能
功能实现的思路:当通常一个网站需要注册用户信息的时候,往往会让用户起一个名字,但一般要求这个用户名称是不能重复的,为了判断新注册的用户填写的用户名是否已经存在,需要对填写的用户名称进行判断,实际项目开 ...
- hnctf安恒--蜘蛛侠呀
这题不会做,赛场被吊打,事后才明白 首先解压看到是流量包,放在wireshark,过滤http很明显看到no_flag.zip,当时想这是个关键点,然后把时间都浪费在这上了,赛后发现并没有传输数据的包 ...
- ios开发中字符串的常用功能总结
1.分割字符串 NSString * str1 = @"123/456"; NSArray * arr1 = [str1 componentsSeparatedByString:@ ...
- C_求最大连续子序列和
题目: 输入一组整数,求出这组数字子序列和中最大值.也就是只要求出最大子序列的和,不必求出最大的那个序列.例如: 序列:-2 11 -4 13 -5 -2,则最大子序列和为20. 序列:-6 2 4 ...
- YUV420、YUV422、RGB24转换
//平面YUV422转平面RGB24static void YUV422p_to_RGB24(unsigned char *yuv422[3], unsigned char *rgb24, int ...
- Linux脚本程序
#!/bin/bash # array-ops.sh: 数组更多有趣的用法. array=( zero one two three four five ) # 元素 ]} # zero } # zer ...
- Python的pandas
pandas 是python中很重要的组件,网上关于pandas 的文章也很多,比如Python科学计算之Pandas 和 Python数据分析入门 Pandas基于两种数据类型:series与dat ...
- python3 HTTP Error 403:Forbidden
问题描述初学python,在用python中的urllib.request.urlopen()和urllib.request.urlretrieve方法打开网页时,有些网站会抛出异常: HTTP Er ...
- c++中POD类型和non-POD类型
对于一个array来说: For POD-types, a shallow copy or memcpy of the whole array is good enough, while for no ...