“通知中心”模式是否会鼓励程序设计的好坏?


13

有时我遇到这些消息中心式的API,例如Cocoa NSNotificationCenter:http : //developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

通常,这些API提供您在其上订阅或广播消息/事件的全局访问点。我认为这是一个问题,因为它鼓励使用扁平且非结构化的程序体系结构,其中的依赖关系在API中不是显式的,而在源代码中则是隐藏的。您不必考虑对象的所有权和层次结构,而可以使程序中的任何对象导致在任何地方调用任何代码。但这也许是一件好事吗?

这种模式通常会鼓励程序设计的好坏,为什么呢?它会使代码更难或更容易测试吗?

如果这个问题太模糊或太宽泛,请原谅我。我正在努力避免像这样大量使用API​​的潜在后果以及使用它的不同方式。

编辑:我猜想我最大的问题是这种API依赖于依赖关系和对象耦合,并且可以通过以下示例进行说明:

myObj = new Foo();
myOtherObj = new Bar();
print myOtherObj.someValue; // prints 0
myObj.doSomething();
print myOtherObj.someValue; // prints 1, unexpectedly, because I never indicated that these objects had anything to do with each other

您是在具体询问此示例还是在总体上对侦听器模式提出疑问?
TheLQ 2010年

我相信这比听众模式更广泛。可以使用定义明确的对象结构“干净地”实现侦听器模式,并在特定对象上注册侦听器。我不确定全局消息/事件中心模式。
Magnus Wolffelt,2010年

Answers:


6

我不会说这会鼓励不良的编程。但是它很容易被滥用。

那么实际的想法是什么?
通知源仅发出通知。它没有对潜在观察者或任何事物的存在做出任何假设。观察者注册它打算处理的通知。观察者不对可能处理的通知有多少潜在来源做出任何假设。

这是一种实现依赖注入的方法,而无需让源知道观察者或观察者知道源。但是,要使整个系统正常工作,您需要为正确的通知连接正确的观察者,并且该系统甚至容易受到拼写错误的影响,因为无法对编译时间进行检查。

当然,最大的危险是,有人会用它来使成吨的对象在全球范围内可用于1-1通话。


6

对于必须扩展的大型系统,异步消息传递是一个很好的架构原则

Java的等效项是JMS,通常被认为是一件好事

这是因为它促进了客户代码与实际为消息提供服务的代码之间的脱钩。客户代码只需要知道在哪里发布他们的消息。服务代码只需要知道在哪里提取消息。客户和服务彼此之间一无所知,因此可以根据需要彼此独立地进行更改。

您可以轻松地将消息中心的URI外部化以使其可配置,而不嵌入到源代码中。


4

这是典型的Oberserver Pattern实现(或有时称为Listener模式或有时称为Subscriber / Publisher模式)。在行为有用的应用程序中,这是一个很好的实现模式。如果没有为解决方案增加任何价值,则不应实施任何模式。

从您的问题看来,您似乎担心的是,有关NotificationCenter的一切都知道,而且全局性问题很糟糕。有时候,是的,全球形势不好。但是,让我们看看替代方案。假设您有2个组件,在此示例中,它们的作用或作用无关紧要。Component1包含一些以某种方式作用或更改过的数据。Component2想知道对Compoent1管理的数据类型的任何更改。Component2是否应该知道Component1的存在?还是最好让Component2订阅/收听一条消息,告诉它应用程序中某个组件的某些内容更改了它感兴趣的某些数据?现在以该示例为例,将其乘以数十个或更多个组件,您可以看到模式的值所在。

是针对每种情况的完美解决方案吗?它是否在组件之间抽象了通信并提供了更宽松的耦合,是的。


1
在Wikipedia上阅读,观察者模式定义似乎不包括全球可用的事件中心。如果将事件中心传递到所有相关对象的构造函数/方法中,则我认为这是一个很好的模式。确实是全球接入点及其状态使我不确定。
Magnus Wolffelt,2010年

0

它对事件驱动的系统很有用,并且比让一堆观察者相互观察更好,因为您不太可能因观察者无意间引发事件的无限循环而陷入困境。在过去的VB时代,这是一个真正的问题,当时您具有事件驱动的ActiveX控件,这些控件可以与事件处理程序相互连接。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.