简介
观察者模式由称作发布-订阅者模式或消息机制,该模式定义一种依赖关系,旨在解决主体对象与观察者之间功能的耦合。
例如案例:想实现一个评论模块,当用户发送消息时,在展示模块末尾追加新的评论,同时用户消息模块中的消息数量会相应增加,删除评论时,用户消息模块数量减少。但是该评论模块之前有有多个开发人员参与,模块之间闭包独立,不想让新实现的代码参与到之前的项目代码中,那么观察者模式就是解决该需求的利器。
实现
创建观察者对象
首先需要先创建一个观察者对象,该对象里面有一个消息容器,并且存在订阅消息,取消订阅消息,发送订阅消息这三个动作方法。
var Observer = (function () {
var _message = {};
return {
//注册订阅信息
register: function () {},
//取消订阅信息
remove: function () {},
//发送订阅信息
send: function () {},
};
})();
以上已经形成观察者对象的雏形,接下来就是实现这三个方法了。register作用是将订阅者注册的消息推入消息队列,因此该方法接收两个数,消息类型及相应的处理动作。
register: function (type, fn) {
//如果该消息类型尚未存在则先创建一个消息类型
if (typeof _message[type] === undefined) {
_message[type] = [fn];
} else {
//如果此消息类型存在了,则向该类型的消息序列中推入一条执行方法
_message[type].push(fn);
}
}
send方法作用是当观察者发布一条消息时,将所有订阅者订阅的消息一次性全部执行。该方法接收两个参数,消息类型及动作执行时需要传递的参数。
send: function (type, args) {
//校验当前消息队列中有没有注册该类型
if (!_message[type]) return;
//定义消息信息
var events = {
type: type,
args: args || {},
};
i = 0;
len = _message[type].length;
//遍历消息动作
for (; i < len; i++) {
//依次执行注册消息对应的动
_message[type][i].call(this, events);
}
}
最后一个功能便是注销方法remove,其功能是将订阅者注销的消息从消息队列中移除,因此我们需要两个参数,消息类型和要执行的某一个动作。
remove: function (type, fn) {
//如果该消息动作队列存在
if (_message[type] instanceof Array) {
var i = _message[type].length - 1;
for (; i >= 0; i--) {
//如果该动作存在则在消息动作序列中移除相应动作
_message[type][i] == fn && _message[type].splice(i, 1);
}
}
}
三个方法均已经实现,下面就来测试吧
var fn_1 = function (param) {
console.log("type_1_1", param);
};
var fn_2 = function (param) {
console.log("type_1_2", param);
};
var fn_3 = function (param) {
console.log("type_2_1", param);
};
var fn_4 = function (param) {
console.log("type_2_2", param);
};
Observer.register("type_1", fn_1);
Observer.register("type_1", fn_2);
Observer.register("type_2", fn_3);
Observer.register("type_2", fn_4);
Observer.remove("type_2", fn_4);
Observer.send("type_1", "吃饭啦!");
Observer.send("type_2", "唱k啦");
//打印结果
//type_1_1 {type: "type_1", args: "吃饭啦!"}
//type_1_2 {type: "type_1", args: "吃饭啦!"}
//type_2_1 {type: "type_2", args: "唱k啦"}
代码地址:https://github.com/CcXxWw112233/base_demo/tree/master/designMode/observer