js设计模式——发布订阅模式
概念
发布订阅模式又叫观察者模式,它定义对象间一对多的依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都将得到通知。
案例
在js设计模式与开发实践一书中使用的是楼盘信息更新发布的案例。大概内容是:想要买房的人们会订阅自己想要的房产信息,如果房产信息有更新,就会发布给这些人。
比如佩奇想买一个房子,他可以在售楼处(salesOffices)去订阅这类房产消息,售楼处会将佩奇订阅的信息填写(listen)在客户订阅表中(clientList),当有房子出来时,售楼处就会发送(trigger)信息给佩奇。
主要内容就是:
salesOffices={ clientList:[], listen:function, trigger:function }
代码如下:
<!DOCTYPE html>
<html>
<head>
<title>发布订阅</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
</body>
<script type="text/javascript">
var consoleText=function (text) {
// body...
let body=document.body;
let div=document.createElement('div');
div.innerHTML=text;
body.appendChild(div);
}
//简单发布-订阅模式
var salesOffices={};
salesOffices.clientList=[];
salesOffices.listen=function(fn){
this.clientList.push(fn);
}
salesOffices.trigger=function(){
for(var i=0,l=this.clientList.length;i<l;i++){
this.clientList[i].apply(this,arguments);
}
}
salesOffices.listen(function(price,s){
consoleText('佩奇您好,现在有新楼盘:价格:'+price+",面积:"+s);
})
salesOffices.listen(function(price,s){
consoleText('小红您好,现在有新楼盘:价格:'+price+",面积:"+s);
})
salesOffices.trigger(6000000,120);
</script>
</html>
如果现在佩奇发现房价太高了,自己的预算只能付得起80平房子的首付,售楼处再给佩奇发120平的房子只会扎佩奇的心,所以佩奇只想订阅80平的房子的消息。
这时候只需要将订阅表分为不同的类型,想要哪种房子的消息就去哪张表填写信息,现在佩奇的信息只能出现在80平的表上了。
当有80平的信息出来时,只需给将80平订阅表的用户发送消息即可
salesOffices={ clientList:{ square80:[], square120:[], }, listen:function, trigger:function }
代码如下:
<!DOCTYPE html>
<html>
<head>
<title>发布订阅</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
</body>
<script type="text/javascript">
var consoleText=function (text) {
// body...
let body=document.body;
let div=document.createElement('div');
div.innerHTML=text;
body.appendChild(div);
}
//可选类型发布-订阅模式
var salesOffices={};
salesOffices.clientList={};
salesOffices.listen=function(key,fn){
//将key类型的订阅存储起来
if(!this.clientList[key]){
this.clientList[key]=[]
}
this.clientList[key].push(fn);
}
salesOffices.trigger=function(){
let key=Array.prototype.shift.call(arguments);
fns=this.clientList[key];
if(!fns||fns.length===0){
return false;
}
for(var i=0,l=fns.length;i<l;i++){
fns[i].apply(this,arguments);
}
}
salesOffices.listen("square80",function(price){
consoleText('小明您好,现在有新楼盘80平:价格:'+price);
})
salesOffices.listen("square80",function(price){
consoleText('小李您好,现在有新楼盘80平:价格:'+price);
})
salesOffices.listen("square110",function(price){
consoleText('小红您好,现在有新楼盘110平:价格:'+price);
})
salesOffices.trigger("square80",12000000);
</script>
</html>
佩奇之后找到了心仪的房子,已经不需要售楼处再发消息了,所以还有取消订阅的功能。
而这种发布订阅的模式很有用,很多行业都可以使用它,所以如果能安装即用就会很nice
代码如下
<!DOCTYPE html>
<html>
<head>
<title>发布订阅</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
</body>
<script type="text/javascript">
var consoleText=function (text) {
// body...
let body=document.body;
let div=document.createElement('div');
div.innerHTML=text;
body.appendChild(div);
}
//通用发布订阅模式
var event={
clientList:{},
listen:function(key,fn){
if(!this.clientList[key])
this.clientList[key]=[];
this.clientList[key].push(fn);
},
trigger:function(){
var key=Array.prototype.shift.call(arguments);
var fns=this.clientList[key];
if(!fns||fns.length===0)
return false;
for(var i=0,l=fns.length;i<l;i++){
fns[i].apply(this,arguments);
}
},
remove:function(key,fn){ //取消订阅
var fns=this.clientList[key];
if(!fns){// 如果 key 对应的消息没有被人订阅,则直接返回
return false;
}
if(!fn){ // 如果没有传入具体的回调函数,表示需要取消 key 对应消息的所有订阅
fns&&(fns.length=0);
}else{
for(var l=fns.length;l>=0;l--){
if(fns[l]===fn){
fns.splice(l,1);
}
}
}
}
}
var installEvent=function(obj){
for(let i in event){
obj[i]=event[i];
}
}
var salesOffices={};
installEvent(salesOffices);
//key的选择,我觉得应该是某个变化的条件
salesOffices.listen("square80",f1=function(price){
consoleText('小明您好,现在有新楼盘80平:价格:'+price);
})
salesOffices.listen("square80",f2=function(price){
consoleText('小李您好,现在有新楼盘80平:价格:'+price);
})
salesOffices.listen("square110",f3=function(price){
consoleText('小红您好,现在有新楼盘110平:价格:'+price);
})
salesOffices.remove("square80",f2);
salesOffices.trigger("square80",80);
</script>
</html>

浙公网安备 33010602011771号