2014-01-30 65 views
5

我一直在各種上下文中使用Dojo,從來沒有找到關於事件與主題的很好的解釋。我使用這兩種機制的理解如下:Dojo:主題vs事件,應考慮哪些設計考慮因素?

  • 兩者都是事件或更一般的消息機制。
  • 兩者的工作方式差不多,因爲您通過設置回調來訂閱主題/事件。
  • 事件與對象/小部件緊密耦合,因爲您需要實際的對象或小部件實例來註冊特定事件的偵聽器。
  • 另一方面,主題機制提供了更加分離的方法,因爲您可以在不知道哪個組件正在發佈主題的情況下訂閱任何主題,甚至不知道該主題是否會發布。

在使用Dojo開發定製窗口小部件時,我曾經多次使用這種方法,讓它們發佈到某些主題。其他組件會訂閱這些主題並做出適當的反應。但是,這導致很難遵循的代碼,因爲當你找到一個訂閱特定主題的代碼時,你開始想知道誰正在發佈到該主題,反之亦然。目前,我傾向於讓自定義小部件提交事件並讓控制器監聽這些事件並將它們分派給其他應對這些事件作出反應的小部件。

所以在第一種方法中,主題機制是小部件之間的粘合劑,但它是分散的,這使得難以在我的經驗中維護代碼的長期。在第二種方法中,控制器類(遵循MVC模式)是膠水,它集中了事件處理。

我很想知道這是否是對這兩種機制的正確理解。在選擇其中一種(或混合它們)時,我應該考慮任何設計考慮因素。任何關於該主題的精心討論的指針都會受到讚賞。我一直在尋找:http://dojotoolkit.org/documentation/tutorials/1.9/events/,但主要描述了這兩種機制如何工作,但對如何構建複雜應用程序沒有深入瞭解。

回答

6

我對你的主題和事件有完全相同的想法。由於JavaScript是事件驅動的,所以當然都是事件 - 就像你在第一點描述的那樣。

事件確實耦合到小部件本身,而主題不是。我通常把它看作如下:

  • 當你有主從一種結構(就像許多項目的列表),然後使用widgets和事件可能是處理問題的最佳途徑。
  • 當兩個部件彼此不相關時,主題可能是彼此之間進行通信的最佳方式。

你說得對,話題讓人很難知道起源是什麼,但如果你仔細想想,你就不需要知道起源。這些主題爲您提供了一個將源與目標分離的API,從而使您無需知道源。因爲這兩個小部件都是不相關的(這是我之前描述的方法),所以在維護代碼時通常不需要知道原點是什麼。

你需要的是一個寫得很好的API,並確保源作爲目的地跟隨它。如果API更改(代碼維護),則可以使用IDE找出哪些小部件正在發佈/訂閱(例如通過搜索主題名稱)並確保每個小部件都已更新。

您也可以選擇封裝的發佈/訂閱的行爲,並通過創建這樣的模塊,提供了更高級API:

define([ "dojo/topic", "dojo/_base/array" ], function(topic, arrayUtils) { 
    var MY_TOPIC = "/my/topic"; 

    var module = { 
     observers: [], 
     notify: function(/** String */ name, /** Integer */ age) { 
      topic.publish(MY_TOPIC, { 
       name: name, 
       age: age 
      }); 
     }, 
     addObserver: function(/** Function */ callback) { 
      return this.observers.push(callback) - 1; 
     }, 
     removeObserver: function(/** Integer */ index) { 
      this.observers[index] = null; 
     } 
    }; 

    topic.subscribe(MYTOPIC, function(data) { 
     arrayUtils.forEach(module.observers, function(observer) { 
      if(observer !== null && data.name !== undefined && data.age !== undefined) { 
       observer(name, age); 
      } 
     }); 
    }); 

    return module; 
}); 

發佈使用notify()功能(提供正確的功能參數)和你添加/刪除觀察員與其他功能。然後,您將使這個組件成爲您的唯一訂閱者,並通知所有觀察者。

這種方式你不需要知道關於這個話題和API是統一的。您只需確保回調函數正確使用參數。要維護代碼,只需更改高級API並查找使用此高級組件的模塊。由於它位於require()函數中,所以更容易檢測。

當我使用主題時,我通常會創建一個像這樣的高級API(可能會根據其用途而改變)。但我認爲所提出的觀點很清楚,改變主題並修改發送的數據更容易。

0

從設計模式和軟件體系結構的角度來看,似乎是在dojo中實現流量的完美機制。找到一篇基本概念爲here的文章。

+0

嗨Johannes,歡迎來到Stack Overflow。關於你的答案的一點建議:當這個鏈接可以回答這個問題時,最好在這裏包含答案的基本部分,並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。有關更多詳情,請參閱[答案]。 –