JavaScript 中介者模式與觀察者模式有何不同?


http://addyosmani.com/resources/essentialjsdesignpatterns/book/#detailmvp

感覺二者非常像,都是pub/sub機制,如何進行區分?分別在什么不同的場景中進行應用?

  • 在Obsever模式中, 不存在封裝約束的單一對象。Observer 和 Subject 必須合作才能維持約束。
  • Communication(通訊)模式由觀察者和目標互聯的方式決定:單一目標通常有很多觀察者,有時一個目標的觀察者是另一個觀察者的目標
  • Mediator 和 Observer  都能促進松耦合,然后Mediator 模式通過限制對象嚴格通過Mediator 進行通信來實現這個個目的
  • Observer 模式創建觀察者對喜愛那個,觀察者對象向訂閱它們的對喜愛那個發布其感興趣的事件。

在GoF的原文中是這樣描述觀察者模式的:

  • One or more observers are interested in the state of a subject and register their interest with the subject by attaching themselves. When something changes in our subject that the observer may be interested in, a notify message is sent which calls the update method in each observer. When the observer is no longer interested in the subject's state, they can simply detach themselves.
  • 具體應用場景是,當subject的某個動作需要引發一系列不同對象的動作(比如你是一個班長要去通知班里的某些人),與其一個一個的手動調用觸發的方法(私下里一個一個通知),不如維護一個列表(建一個群),這個列表存有你想要調用的對象方法(想要通知的人);之后每次做的觸發的時候只要輪詢這個列表就好了(群發),而不用關心這個列表里有誰,只用關心想讓誰加入讓誰退出


這個列表就叫做ObserverList,它有一些維護列表方法:

function ObserverList(){
  this.observerList = [];
}
ObserverList.prototype.Add = function( obj ){};
ObserverList.prototype.Empty = function(){};
ObserverList.prototype.Count = function(){};
ObserverList.prototype.Get = function( index ){};
ObserverList.prototype.Insert = function( obj, index ){};
ObserverList.prototype.IndexOf = function( obj, startIndex ){};
ObserverList.prototype.RemoveAt = function( index ){};

而我們的subject只用關心兩件事:1.維護這個列表,2.發布事件

function Subject(){
  this.observers = new ObserverList();
}

Subject.prototype.AddObserver = function( observer ){
  this.observers.Add( observer );
};  

Subject.prototype.RemoveObserver = function( observer ){
  this.observers.RemoveAt( this.observers.IndexOf( observer, 0 ) );
};  

Subject.prototype.Notify = function( context ){
  var observerCount = this.observers.Count();
  for(var i=0; i < observerCount; i++){
    this.observers.Get(i).Update( context );  
    // 在這里假設的是列表里的每個對象都有update方法,但個人覺得這個列表里也可以是不同對象的不同方法,只要能接受當前上下文作為參數, 可以這樣執行:
    // subscription.callback.apply( subscription.context, args );
  }
};

中介模式(Mediator Pattern)

讓我們假設這樣一個場景: 有一個Manager一聲令下,需要讓工人A和工人B開工,代碼可以是這樣的

Manager.start = function () {
    A.work();
    B.work();
}

其實還可以這么寫,新增一個中介模塊,這個模塊有存儲了Manager的常用命令比如start,stop,resume,每一個命令其實維護的也是一個列表,比如start的列表下存儲了所有員工的start方法:

Mediator["start"] = [
    {
        name: 'A',
        callback: 'work'
    },
    {
        name: 'B',
        callback: 'workAgain'
    },
]

所以Manager的方法可以重寫為

Manager.start = function () {
    Mediator.publish('start')   // publish 為觸發命令函數,以此來觸發start命令下維護的所有回調函數
}

代碼細節就不展示了,主要體現這么一個機制,而如果某個員工要提交自己的work方法供老板調用的話,只要注冊一下就好了

Mediator.subscribe('C', function callback() {});

 

問題是新增加一個中介模塊的好處是什么?

1.低耦合!如果不是經理要讓員工開始工作,是董事長怎么辦,或者是部門主管怎么辦,難道都要這么寫

XXX.start = function () {
    A.work()
    B.work();
}

都要把A.work什么抄一遍?當然不是,只要給中介模塊發出命令就好了,
2.模塊之間不需要進行通信,只要負責廣播和監聽事件就好了
3.在模塊化的javascript中,中介模塊能提高可維護性:是否啟動某個模塊,有沒有權限啟動某個模塊,異步加載某些模塊,模塊之間的依賴關系,某些模塊啟動失敗了怎么辦。這些邊界條件都可以交給它來判斷,而其他模塊只關心實現自己邏輯就好了
最后打個比方,中介模塊真的就像房屋中介一樣!如果你是房東,你只需要下令一聲“我要找人租房”,他們就自然會生成那個列表,你不用直接和房客打交道。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM