什么是发布-订阅者模式
我们在使用发布-订阅者模式之前,先了解什么是发布-订阅者模式。简单来说,发布订阅者模式就是一种一对多的依赖关系。多个订阅者(一般是注册的函数)同时监听同一个数据对象,当这个数据对象发生变化的时候会执行一个发布事件,通过这个发布事件会通知到所有的订阅者,使它们能够自己改变对数据对象依赖的部分状态。
这样看来,一个完整的订阅发布模式,由发布者、订阅者、消息管理器三部分组成。
我们 为什么/什么时候 要使用这种模式
首先,如果一个数据或者事件的变化会对许多事件产生影响。例如:我们通过websocket从后台实时获取数据,当返回的数据为 @end 时,需要执行关闭数据流,更改数据显示,更新设备状态等等,在不使用订阅开发者模式时,当接收到 @end 后,我们注册一个函数,需要在该函数中写n个函数的执行,但是使用设计者模式,只需要注册一个 @end 的发布函数,其他函数订阅该函数,当发布函数执行后会发布信息,其订阅者会自动更新状态。
- 耦合性低
- 便于代码的维护
在js中的实现
所有代码都在项目中亲测有效,且效率较高
1. 定义一个发布者对象,该对象有订阅者列表和发布函数两个属性。
function Deliver() {
this.subscribers = [];
}
Deliver.prototype = {
constructor: Deliver,
deliver: function( message ) {
this.subscribers.forEach( function( fun ) {
fun( message );
} );
return this;
}
}
2. 为发布者对象添加订阅方法和退订方法
//订阅事件
function subscribe( subscriber, deliver ) {
var hasExists = false,
isFunction = Object.prototype.toString.call( subscriber ) === '[object Function]';
if( isFunction && deliver instanceof Deliver ) {
hasExists = deliver.subscribers.some( function( fun ) {
return fun === subscriber;
} );
if( !hasExists ) {
deliver.subscribers.push( subscriber );
}
}
}
//退订subscriber事件
function unSubscribe( subscriber, deliver ) {
var isFunction = Object.prototype.toString.call( subscriber ) === '[object Function]';
if( isFunction && deliver instanceof Deliver ) {
deliver.subscribers = deliver.subscribers.filter( function( fun ) {
return fun !== subscriber;
} )
}
}
3. 实例化一个发布者并为其添加订阅者
var endDeliver = new endDeliver();
(function(window){
subscriber(endHandle , endDeliver);
subscriber(endHandle2 , endDeliver);
if(webSocket.data == "@end"){
endDeliver.deliver();//当返回数据为end时,end发布者发布消息
}
})(window)
function endHandle(){
console.log("已执行结束")
}
function endHandle2(){
console.log("重新开始执行函数");
}
4. 运行结果
四、应用心得
- 可以注册一个空的发布者,即在满足某些条件时发布一些空消息,而订阅者的执行也不需要传递任何的参数。主要适用于状态的改变引起的函数执行。
- 注册带有参数的发布者,当数据改变时,将数据作为参数传递给各个订阅者,订阅者根据返回的数据进行状态的更新。主要适用于对数据的渲染及判断。
//实例化一个数据发布者
var messagePost = new Deliver();
//该发布者有两个订阅者
subscriber(handle1 , messagePost);
subscriber(handle2 , messagePost);
//两个订阅者分别执行的函数为
function handle1(data){
console.log(data);
}
function handle2(data){
$(".dome").html(data.ip);
}
//在数据发生改变的时候发布者发布消息
websocket.onmessage = function(evet){
messagePost.deliver(event.data)
}
//执行结果
当通过websocket返回的数据时,messagePost会发布消息,handle1 handle2会相继执行更新自己的数据。