这周还是学习的心路历程,主要是对观察者模式,订阅-发布模式与自定义事件进行学习。
首先,主要是对两种模式进行对比
观察者模式
思路:
1、分别有三个角色,分别是ObserverList
,Subject
,Observer
。
2、ObserverList:观察者列表,用于存放观察者对象(下一条的Observer),供主体Subject维护。
3、Observer:观察者对象,存放在列表中待命,用于更新视图,如果接到主体Subject的命令则更新,换句话说就是用来观察Subject什么时候发命令。
4、Subject:主体,个人理解它就是“被观察者对象”,被一群Observer围观奸视,只要一说话(发布notify),各个Observer就会有所动作。具体场景可以联想一下某岛的视频(就在此时舍友的电脑忽然响起:澳门赌场开业啦!!)
从生活中理解观察者模式:
像别的大牛一样,我也举个栗子会比较方便理解。
比如在工作中的时候,大家都在加班干活儿,但是有的人手上的活儿已经做完了,有的人手上还没完,完成了就上报工作,直到所有人都完成了,在老大手上调试完毕没有bug才能离开。
假如你也是在团队里的一个开发者,你已经完成了,这个时候肯定压抑不住想下班的心情。然后你就隔三差五去问老大的进度,你隔壁的小伙伴也完成了,也跟你一样隔三差五的去问。
老大(Subject)
觉得烦了,就把你们的QQ号(Observer)
加上了,拖进一个分组(ObserverList)
,然后当所有组员都完成调试好了,就给你们群发消息(Subject.notify)
,以上就是观察者模式了
下面我贴一下各对象的方法,具体实现在顶部的link可以找到(我只是想练习一下写注释2333)。
ObserverList:
function ObserverList() {
// 初始化观察者列表
}
/**
* add
* 添加方法
* 用于往 “观察者列表” 添加 “观察者对象”
* @param {Object} observer 观察者对象
*/
ObserverList.prototype.add = function( observer ) {
// code...
}
/**
* count
* 统计方法
* 获取 “观察者列表” 的长度
*/
ObserverList.prototype.count = function() {
// code...
}
/**
* get
* 获取 “观察者对象” 方法
* 通过索引从 “观察者列表” 获取 “观察者对象”
* @param {Number} index
*/
ObserverList.prototype.get = function( index ) {
// code...
}
/**
* indexOf
* 查找方法
* 查看 “观察者对象” 在列表中的位置,没有则返回-1
* @param {Object} observer 观察者对象
* @param {Number} startIndex 起始索引
*/
ObserverList.prototype.indexOf = function( observer, startIndex ) {
// code...
}
/**
* removeAt
* 删除方法
* 通过索引删除列表中对应的“观察者对象”
* @param {Number} index 需要删除的索引
*/
ObserverList.prototype.removeAt = function( index ) {
// code...
}
Observer:
function Observer() {}
/**
* update
* 更新函数 / 发布函数
* 用于更新视图
* @param {any} context 更新内容
*/
Observer.prototype.update = function(context) {
// code...
}
Subject:
/**
* Subject
* 主体对象
* 用于维护观察者列表以及发布更新内容
*/
function Subject() {
// 初始化观察者列表
}
/**
* addObserver
* 添加观察者方法
* 顾名思义添加“观察者对象”
* @param {Object} observer 观察者对象
*/
Subject.prototype.addObserver = function( observer ) {
// code...
}
/**
* removeObserver
* 删除对象
* 删除“观察者对象”
* @param {Object} observer 观察者对象
*/
Subject.prototype.removeObserver = function( observer ) {
// code...
}
/**
* notify
* 发布消息
* 向观察者对象发布消息
* @param {any} context 向Observer.update更新内容。
*/
Subject.prototype.notify = function( context ) {
}
订阅-发布模式
思路:
1、订阅-发布模式就比较简单,有三个基本方法:publish
,subscribe
,unsubscribe
,还有一个topicList
。
2、topicList:用于存放订阅消息的列表。
3、subscribe:用于向topicList注册的方法。
4、publish:用于告诉topicList,然后再发布对应topic消息的方法。
5、unsubscribe:用于告诉topicList,然后再删除对应topic的方法。
从生活中理解订阅-发布模式:
假如你也是在团队里的一个开发者,你已经完成了,这个时候肯定压抑不住想下班的心情。然后你就隔三差五去问老大的进度,你隔壁的小伙伴也完成了,也跟你一样隔三差五的去问。
老大(Subject)
觉得烦了,就把你们的QQ号(Observer)
加上了。
讲到这里,肯定有很多同学有疑问,这TM跟观察者没区别啊!别着急,这里打断了你们的阅读就是为了引出不一样的地方。
刚刚讲到老大把你们的QQ号(Observer)
加上了,就把你们都拉进一个群里,然后当所有组员都完成调试好了,就给你们群发消息(Subject.notify)
,以上就是订阅-发布模式了
/**
* PubSub
* 订阅发布类
* 用于存放初始化的数据
*/
function PubSub() {
this.pubsub = {};
this.topics = {};
this.subUid = -1;
}
/**
* publish
* 用于发布内容
* @param {string} topic 发布主题(订阅事件的名字)
* @param {any} args 要发布的内容
*/
PubSub.prototype.publish = function( topic, args ) {
if ( !topics[topic] ) {
return false;
}
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func( topic, args );
}
return this;
};
/**
* subscribe
* 用于注册内容
* @param {string} topic 注册主题(订阅的事件名)
* @param {function} func 主题需要执行的事件
*/
PubSub.prototype.subscribe = function( topic, func ) {
if (!topics[topic]) {
topics[topic] = [];
}
var token = ( ++subUid ).toString();
topics[topic].push({
token: token,
func: func
});
return token;
};
/**
* subscribe
* 删除注册内容
* @param {string} token 事件的token
*/
PubSub.prototype.unsubscribe = function( token ) {
for ( var m in topics ) {
if ( topics[m] ) {
for ( var i = 0, j = topics[m].length; i < j; i++ ) {
if ( topics[m][i].token === token ) {
topics[m].splice( i, 1 );
return token;
}
}
}
}
return this;
};
总结一下:
观察者模式
与订阅-发布模式
可以说过程是一样的,因为都是用来监听被观察者事件有没被触发。
也可以说是不一样的,因为观察者模式
是一对一的方式,也就是上面的例子,老大发个消息还要群发。而订阅-发布模式
更像是广播的形式,就比如上面的例子,创建一个群来发送消息,不管你接到没反正我是发了,你有去看的话也肯定看到了。
讲到这里,自然也是离不开自定义事件了。
自定义事件的设计思想,与订阅发布模式的概念是吻合的。
咳咳,好像有点长了,下周再写吧…