2014-01-30 187 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。关于你的答案的一点建议:当这个链接可以回答这个问题时,最好在这里包含答案的基本部分,并提供参考链接。如果链接页面更改,则仅链接答案可能会失效。有关更多详情,请参阅[答案]。 –