观察者设计模式和C#事件委托模型

5

看起来观察者设计模式是通过C#的事件委托模型内置的。是否有任何原因需要按照经典方式实现它?

敬礼
123开发者

6个回答

6
通常,语言内置的事件模型对于观察者模式来说已经足够了。没有必要用不同的方式实现它,因为你只是在重新创建事件。
话虽如此,有时人们会改变“标准”事件模式,但这种情况很少见。例如,我曾看到过人们想异步地引发事件的情况。通常我不建议这样做(我个人认为最好由订阅者处理),但仍然可以通过标准的C#事件来处理,只是引发事件的方式略有变化(使用GetInvocationList并异步调用委托)。

2
我非常喜欢C#的事件系统。在我看来,唯一的缺点是,因为用户不明显地拥有附加/分离API方法调用,很多人不知道在完成对象后将事件处理程序分离/删除,从而使对象远离垃圾收集器。 - Matt
@Matt,确实!当你的应用程序耗尽内存时,调试这些问题非常有趣。 - Cylon Cat

3

你说得对。观察者模式在C#事件系统中使用委托实现。

你想要更接近传统观察者的原因之一是为了便于领域事件和/或组合应用程序体系结构的聚合。

Jeremy Miller在事件聚合器方面有一篇很好的文章:http://codebetter.com/blogs/jeremy.miller/archive/2009/07/21/braindump-on-the-event-aggregator-pattern.aspx

我使用他的文章创建了我的事件聚合器,并将其放入基于消息的体系结构中,用于我的WinForms / 手持设备应用程序:http://www.lostechies.com/blogs/derickbailey/archive/2009/12/22/understanding-the-application-controller-through-object-messaging-patterns.aspx


2
我认为一般来说,我们没有真正的理由不使用C#委托模型来实现观察者模式。但是,在.Net 4中,他们添加了 IObserver<T>IObservable<T> 接口以实现基于推送的通知系统。因此,我猜这就是您想要使用接口而不是基于事件的模型的情况之一。

哦,太好了!我还没有使用 .net 4,所以我不知道这些。但如果我在 .net 4 中重写我的事件聚合器,那正是我要使用的。 - Derick Bailey
特别是,反应式扩展(一个微软研究项目)充分利用了这个更强大的观察者框架来表达一些非常强大的东西:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx - Dan Bryant

1

我同意.NET的事件处理程序可以满足大多数观察者模式的需求。然而,有几个接口你需要特别注意,尤其是在Silverlight和WPF中。这些接口是INotifyPropertyChanged和INotifyCollectionChanged。它们规定了Silverlight和WPF对数据绑定所期望的具体模式。此外,还有一个实现了INotifyCollectionChanged的ObservableCollection类;在构建Silverlight和WPF界面时,使用它可以省去很多麻烦。


0

我认为在C#中,经典的观察者设计模式被大大简化了。我认为可能存在一些情况,使用经典实现更加“安全”。我想到的是多线程和公共API。如果你按照经典方式进行单元测试,可能会更容易。但是,正如你所提到的,现在有了C#委托的更简单的快捷方式。抱歉,我没有一个明确的答案来说明何时必须使用经典模式。


@Matt 我对此没有明确的答案,但是使用Mocking可能会更容易。 - Jerod Houghtelling
所有当前的模拟系统(如Rhino Mocks、Moq等)都可以轻松支持事件。如果您正在编写自己的模拟,手动(很抱歉...),那么经典的观察者会更容易模拟,因为它只是一个接口而不是委托。但是您不会自己编写模拟,对吧?... 对吧? :) - Derick Bailey
@Derick 正确,我不会自己编写模拟对象。我同时使用Moq和Rhino。在阅读了您对这个原始问题的回答后,我几乎删除了我的回答。您的回答非常好,而我的则含糊不清且缺乏具体性。 - Jerod Houghtelling

0
我会看一下这篇文章: SO上的类似问题 我特别喜欢Jon Skeet的一个评论:

当然。这有点像问:“我应该实现迭代器模式还是使用foreach和IEnumerable?”

这是对这个回答的回应:

嗯,事件可以用来实现观察者模式。事实上,使用事件可以被认为是观察者模式的另一种实现方式。

但是所选的答案非常好并且适用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接