用观察者模式编写一个可被其他对象拓展复用自定义事件系统
观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知
什么是观察者模式?
发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在 JavaScript 开发中,我们一般用事件模型来替代传统的发布—订阅模式。
举个栗子:
卖水果的张老板和王老板都要进一批香蕉,他们的水果都是在一个叫钱多多(下面统称为钱老板)的水果批发商那里进的。当张老板和王老板到钱老板那里进水果的时候,钱老板告诉张老板和王老板,香蕉还没有到货,得过几天才到货。无奈之下,张老板和王老板都把他们的电话号码留在了钱老板那里,嘱咐钱老板,香蕉到货后,第一时间通知他们。
上面钱老板就扮演了发布者的角色,张老板和王老板则扮演的是订阅者角色。在香蕉到货后,钱老板会主动给张老板和王老发消息,让两位老板来取香蕉。这样的好处就是:香蕉没到的这段时间,张老板和王老板可以做其他的事情,不用主动联系钱老板,只需等待钱老板的消息即可。也就是程序代码中的时间上解耦,对象间解耦。
自定义事件
其实观察者模式我们都曾使用过,就是我们熟悉的事件
但是内置的事件很多时候不能满足我们的要求
所以我们需要自定义事件
现在我们想实现这样的功能 定义一个事件对象,它有以下功能
- 监听事件(订阅事件)
- 触发事件(事件发布)
- 移除事件(取消订阅事件)
当然我们不可能只订阅一个事件,可能会有很多
所以我们要针对不同的事件设置不同的”键”
这样我们储存事件的结构应该是这样的
EventList = {evtName1: [回调函数1,回调函数2,...],evtName2: [回调函数1,回调函数2,...],evtName3: [回调函数1,回调函数2,...],
}
代码如下
var createEventSys = function(){return {// 通过on接口监听事件eventName// 如果事件eventName被触发,则执行callback回调函数on: function (eventName, callback) {//如果Event对象没有handles属性,则给Event对象定义属性handles,初始值为{}//handles属性是用来存储事件和回调执行函数的(即存储订阅的事件和触发事件后执行的相应函数方法)if(!this.handles){this.handles={};}//如果handles中不存在事件eventName,则将事件存储在handles中,同时初始化该事件对应的回调逻辑函数集合if(!this.handles[eventName]){this.handles[eventName]=[];}//往handles中的eventName对应的回调逻辑函数集合push回调函数callbackthis.handles[eventName].push(callback);},// 触发事件 eventNameemit: function (eventName) {//如果事件eventName有订阅者,则依次执行事件eventName的订阅者相应的回调方法if(this.handles[arguments[0]]){for(var i=0;i<this.handles[arguments[0]].length;i ){this.handles[arguments[0]][i](arguments[1]);}}},//移除事件 eventNameremove: function (eventName, fn) {//判断事件eventName是否存在fn这个观察者,如果有,则移除事件eventName的fn观察者if(this.handles[eventName]){for(var i=0; i<this.handles[eventName].length; i ){if(this.handles[eventName][i] === fn){this.handles[eventName].splice(i,1);break;}}}}};
}
var Event = createEventSys();
Event.on('test', function (result) {console.log(result);
});
Event.on('test', function () {console.log('test');
});
Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test'//对象person1和对象person2拓展复用自定义系统
var person1 = {};
var person2 = {};
Object.assign(person1, createEventSys());
Object.assign(person2, createEventSys());
person1.on('call1', function () {console.log('person1');
});
person2.on('call2', function () {console.log('person2');
});
person1.emit('call1'); // 输出 'person1'
person1.emit('call2'); // 没有输出
person2.emit('call1'); // 没有输出
person2.emit('call2'); // 输出 'person2'
如上面代码这样,我们用观察者模式就实现了一个基本完善的自定义事件系统。
总结
观察者模式有两个明显的优点
时间上解耦
对象间解耦
在前端开发中,很多地方都适合用观察者模式来做,在适当的地方善用观察者模式
希望这篇文章对大家有帮助,喜欢的话,请关注我,我会持续更新一些技术文章到我的掘金主页,谢谢大家支持!
更多专业前端知识,请上 【猿2048】www.mk2048.com
用观察者模式编写一个可被其他对象拓展复用自定义事件系统相关推荐
- C语言输出长方柱的体积,需要求3个长方柱的体积,请编写一个基于对象的程序。数据成员包括length(长)、width(宽)、 height(高)。要求用成员函数实现以下功能...
需要求3个长方柱的体积,请编写一个基于对象的程序.数据成员包括length(长).width(宽). height(高).要求用成员函数实现以下功能: (1) 由键盘分别输入3个长方柱的长.宽.高: ...
- Java黑皮书课后题第10章:*10.1(Time类)设计一个名为Time的类。编写一个测试程序,创建两个Time对象(使用new Time()和new Time(555550000))
Java黑皮书课后题第10章:*10.1设计一个名为Time的类.编写一个测试程序,创建两个Time对象 题目 程序 代码 Test1.java Test1_Time.java 运行结果 UML 题目 ...
- Java黑皮书课后题第9章:*9.4(使用Random类)编写一个程序,创建一个种子为1000的Random对象,然后使用nextInt(100)方法显示0到100之间的前50个随机整数
Java黑皮书课后题第9章:*9.4(使用Random类)编写一个程序,创建一个种子为1000的Random对象,然后使用nextInt方法显示0到100之间的前50个随机整数 题目 赘述 代码 题目 ...
- C++实现类和对象:编写一个程序,模拟电梯的功能。功能接口包括电梯上行按钮、下行按钮、楼层选择和电梯在行驶过程中的楼层显示。
浙江理工大学信息学院 面向对象程序设计实验报告 实验名称:类的定义与使用 学时安排:3 实验类别:设计性实验 ...
- 编写一个方法参数接收一个字符串,返回一个Date对象(在多种日期格式中找到与字符串匹配的那一个)用到解析异常ParseException
题目:编写一个方法参数接收一个字符串,返回一个Date对象(在多种日期格式中找到与字符串匹配的那一个)用到解析异常ParseException 具体代码如下: import java.text.Par ...
- JAVA类与对象tank_5.编写一个java程序,该程序有两个类:Tank(用于刻画坦克)和Fight(主类)。 已知坦克类如下:...
5.编写一个java程序,该程序有两个类:Tank(用于刻画坦克)和Fight(主类). 已知坦克类如下: public classTank{ double speed; //坦克速度 ...
- 需要求三个长方体的体积,请编写一个基于对象的程序。
// 121218 第八章习题6.cpp : 定义控制台应用程序的入口点. // /* * Copyright (c) 2012, 烟台大学计算机学院 * All rights reserved. * ...
- 需要求三个长方体的体积,请编写一个基于对象的程序
需要求三个长方体的体积,请编写一个基于对象的程序.数据成员包括length(长).width(宽).height(高). (1)由键盘分别输入3个长方体的长.宽.高. (2)计算长方体的体积. (2) ...
- c++类与对象(多文件编程!)(编写一个有关股票的程序,其中有两个类:一个是深圳类shen_stock,另一个是上海类shang_stock。)
#编写一个有关股票的程序,其中有两个类:一个是深圳类shen_stock,另一个是上海类shang_stock.类中有三项私有数据成员:普通股票个数general.ST股票个数st和PT股票个数pt, ...
最新文章
- python人脸识别项目_基于Python与命令行人脸识别项目(系列二)
- 无偏方差为什么除以n-1
- IDA——动态调试Linux上的ELF文件(整合他人博客)
- win7域内桌面黑屏
- linux下搭建博客21天打卡Day6
- HDU 2181 哈密顿绕行世界问题
- ASP.NET WebAPI构建API接口服务实战演练
- 下载SAP hana镜像文件
- 基于单片机PID算法温度控制系统设计(毕设)
- 5、聊聊大名鼎鼎的张正友标定法
- [转]线性插值双线性插值三线性插值
- 关于getdate()的不同的日期格式
- 使用R进行VENN_维恩图或韦恩图_的绘制_2020-11-08
- 灰度图转热力图_热力图下看区域城市密集度,密集度较高的主要在沿海和省会周边...
- 将代码提交到github上
- 2020最火网络新词英文_2020年最流行的话 2020最火网络新词
- EasyDl快速上手教程
- 【物联网】三大厂家NB-IOT卡对比
- C++的成员函数声明与定义 —— 类外定义成员函数以及inline函数
- mmrotate学习记录
热门文章
- ajax的url怎么将后缀补上_蜂蜜杏仁怎么做?杏仁和蜂蜜腌制方法
- 六年级计算机课学什么时候,六年级信息技术《进一步了解计算机》教学设计
- c语言作业请输入一个运算符,C语言书面作业1(有答案版)..doc
- java 生成校验验证码_java 验证码生成与校验
- 转: 微博的多机房部署的实践(from infoq)
- JBOSS内存溢出处理
- 基本算法研究1-冒泡排序算法测试
- java tomcat自动安装教程_Tomcat:基础安装和使用教程
- 用数组存储循环序号的数据
- 中国计算机手机全部被黑,云南一高校电脑全被黑