JS设计模式2-发布/订阅模式和观察者模式

发布(Publish)/订阅(Subscribe)模式是一种和观察者(Observer)模式很相似的设计模式,以至于很多人把这两种模式看作是同一种模式。

在观察者模式中的Subject就像一个发布者(Publisher),而观察者(Observer)完全可以看作一个订阅者(Subscriber)。subject通知观察者时,就像一个发布者通知他的订阅者。


1.观察者模式和发布/订阅模式的概念
  • 观察者模式
    目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法。

    JS设计模式2-发布/订阅模式和观察者模式_第1张图片
    observer.png

  • 发布/订阅模式
    订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者注册到调度中心的处理代码。

    JS设计模式2-发布/订阅模式和观察者模式_第2张图片
    pubsub.png

我们再用一个图来直观地感受一下两种模式之间的区别:

JS设计模式2-发布/订阅模式和观察者模式_第3张图片
common.jpg

观察者模式和发布/订阅模式的区别是:

    1. 从上面的图片中可以看到,最大的区别是调度的地方。虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者),但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
    1. 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。

2.观察者模式实现

下面这段代码摘抄自JavaScript 设计模式一书

  • 2.1对观察者和被观察者进行建模:


    JS设计模式2-发布/订阅模式和观察者模式_第4张图片
    2-1.png
  • 2.2 扩展函数
function extend(extension,obj){ 
   for(var key in extension){
   obj[key]=extension[key]; }
}
  • 2.3使用范例
html:


script: //注意要把2-1和2-2封装好的函数copy进来 //我们DOM元素的引用 var controlCheckbox=document.getElementById("mainCheckbox"), addBtn=document.getElementById("addNewObserver"), container=document.getElementById("observersContainer"); //具体的被观察者 //Subject类扩展controlCheckbox类 extend(new Subject(),controlCheckbox); //点击checkbox将会触发对观察者的通知 controlCheckbox["onclick"]=new Function("controlCheckbox.notify(controlCheckbox.checked)"); addBtn["onclick"]=AddNewObserver; //具体的观察者 function AddNewObserver(){ //建立一个新的用于增加的checkbox var check =document.createElement("input"); check.type="checkbox"; //使用Observer类扩展 extend(new Observer(),check); //使用定制的Update函数重载 check.update=function(value){ this.checked=value; }; //增加新的观察者到我们主要的被观察者的观察者列表中 controlCheckbox.addObserver(check); //将元素添加到容器的最后 container.appendChild(check); }

运行结果截图:


observer-res.png

3.发布/订阅模式实现

发布/订阅在JavaScript的生态系统中非常合适,主要是因为作为核心的ECMAScript 实现是事件驱动的。尤其是在浏览器环境下更是如此,因为DOM 使用事件作为其主要的用于脚本的交互API。


JS设计模式2-发布/订阅模式和观察者模式_第5张图片
pubsub.png
  • 测试
 var messageLogger=function(topics,data){
    console.log("Logging:"+topics+":"+data);
 };


var subscription=pubsub.subscribe("inbox/newMessage",messageLogger);

pubsub.publish("inbox/newMessage","helloworld!"); 
// or
pubsub.publish("inbox/newMessage",["test","a","b","c"]);
// or
pubsub.publish("inbox/newMessage",{
  sender:"[email protected]",
  body:"Heyagain!"
});

  • 运行结果


    pubsub-res.png

关于发布/订阅模式的渐进实现大家可以参考JS设计模式之订阅模式


参考文章:
观察者模式与发布/订阅模式区别
【Javascript设计模式3】-观察者模式
《JavaScript 设计模式》一书

你可能感兴趣的:(JS设计模式2-发布/订阅模式和观察者模式)