【问题标题】:Observer design pattern and C# event delegate model观察者设计模式和 C# 事件委托模型
【发布时间】:2011-03-07 11:07:27
【问题描述】:

观察者设计模式似乎是通过其事件委托模型内置在 C# 中的。有什么理由我可能必须以经典方式实现它吗?

问候
123开发者

【问题讨论】:

    标签: c# design-patterns


    【解决方案1】:

    通常,语言中内置的事件模型足以满足观察者模式。真的没有理由以不同的方式实现它,因为您只是在重新创建事件。

    话虽如此,人们很少改变“标准”事件模式。例如,我见过人们想要异步引发事件的情况。我通常不推荐这样做(我个人认为这在订阅者方面处理得更好),但它仍然可以通过标准 C# 事件来处理,但引发事件略有变化(使用 GetInvocationList 并异步调用委托) .

    【讨论】:

    • 我真的很喜欢 C# 事件系统。恕我直言,它的一个缺点是因为您没有明确地让用户看到附加/分离 api 方法调用,所以很多人在使用完对象后不知道分离/删除事件处理程序.从而使对象远离垃圾收集器。
    • @Matt,确实是的!当您的应用内存不足时,调试这些非常有趣。
    【解决方案2】:

    你是对的。观察者模式是在 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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 哦,太好了!我还没有使用.net 4,所以我不知道这些。但这正是我在 .net 4 中重写它时将用于事件聚合器的内容
      • 特别是 Reactive Extensions(一个 MS 研究项目)很好地利用了这个更强大的观察者框架来表达一些非常强大的东西:msdn.microsoft.com/en-us/devlabs/ee794896.aspx
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我同意经典的观察者设计模式在 C# 中得到了极大的简化。我认为可能存在使用经典实现“更安全”的案例。想到的事情是多线程和公共 API。我认为如果您采用经典方式,单元测试有时可能会更容易。但是,就像您提到的那样,现在使用 C# 委托有一个更简单的快捷方式。抱歉,对于何时必须使用经典模式,我没有明确的答案。

        【讨论】:

        • @Matt 我对此没有明确的答案,但 Mocking 可能更容易。
        • 所有当前的模拟系统(rhino mocks、moq 等)都可以轻松支持事件。如果您正在手动编写自己的模拟(我很抱歉......)那么是的,经典的观察者会更容易模拟,因为它只是一个接口而不是委托。但你不是在滚动你自己的嘲笑,对吧? ... 正确的? :)
        • @Derick 正确我不是在滚动我自己的模拟。我使用最小起订量和犀牛。在阅读了您对这个原始问题的回答后,我几乎删除了我的答案。你的做得很好,而我的则含糊不清。
        【解决方案6】:

        我会看看这个帖子:

        Similar Question on SO

        我特别喜欢 Jon Skeet 的一条评论:

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

        这是对这个说得很好的答案的回应:

        嗯,事件可以用来实现观察者模式。事实上,使用事件可以看作是观察者模式恕我直言的另一种实现。

        但选择的答案相当不错,适用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-24
          • 1970-01-01
          • 1970-01-01
          • 2020-12-28
          • 2010-11-04
          • 2011-09-25
          • 1970-01-01
          • 2011-11-25
          相关资源
          最近更新 更多