【问题标题】:Delegates vs. Observer patterns [closed]代表与观察者模式[关闭]
【发布时间】:2011-07-31 19:34:45
【问题描述】:

对于何时应该使用委托进行间接关联和观察者是否有任何指导方针?

在 C# 中,您可以使用委托进行简单的回调。我猜指向函数的指针和指向成员函数的指针也可以被视为委托(对吗?)。

我意识到确实使用观察者,你需要创建一个接口,并实现它,所以它是更强类型的,关系更正式。对于委托,只要函数签名和可访问性匹配,就可以“挂钩”。

委托是否使观察者模式没有实际意义?您如何决定委托与观察者模式?

【问题讨论】:

  • 顺便说一句:在 .NET 4 中,这样的接口已经存在:IObservable<T>IObserver<T>。您可以使用响应式扩展轻松组合可观察对象和观察者。

标签: c# design-patterns


【解决方案1】:

观察者模式已经以events 的形式为您实现。

事件的优点是它们可以有多个订阅者,而使用委托,你只能有一个。 这使得事件更适合公共接口,以及你没有的场景完全控制谁想要得到通知发生的事情。实际上,事件只是自动管理的委托列表。你必须看看在你的场景中什么更有意义。

编辑:As commenter Rabbi mentions,以上内容并不完全正确,因为任何委托都可以成为多播委托。事件修饰符的目的是创建一个只能在定义它的类中调用的委托。这对于确保在公共接口中的封装非常有用。

【讨论】:

  • 事件只是一种特殊类型的委托。不是这样一个代表可以有多个订阅者吗?我认为一个事件是一个只有运算符'+='和'-='的委托,并且也可以分配一个委托('='),因此您可以在使用委托而不是事件时覆盖所有订阅者。我说的对吗?
  • 事件的 C# 概念对于委托来说或多或少就像属性对于字段一样。您可以更改添加/删除操作的功能,请参见示例 2 here。如果您不这样做,它会在后台为您生成一个MulticastDelegate
  • 是的。我想说的是,事件只使用运算符+=-=,即使您可以通过使用类似属性的addremove 构造来更改这些运算符的行为。无法对事件进行分配(= 运算符)。我可能是错的,因为我懒得尝试。
  • 这个答案是完全错误的。它正在传播互联网上大量的错误信息和混乱。关于这个问题,这也完全是题外话。任何委托都可以是多播委托并指向多个订阅者。事件修饰符的作用是限制从定义类以外的任何对象调用委托函数。下面是 jpierson 的一个更热门的答案,而且不仅仅是直接错误的答案。
  • restrict calling the delegate function from any object other than the defining class. 听起来像encapsulation。这是真的吗?
【解决方案2】:

观察者模式的一个优点是,如果您有大量事件通常总是由感兴趣的一方订阅,那么将单个对象传递给一个方法来订阅这些事件比订阅每个事件要容易得多单独事件。由于 C# 没有为匿名类 as can be done with Java 指定接口和方法,实现观察者模式变得更加费力,因此大多数人还是选择使用事件。

传统观察者模式的另一个好处是它可以更好地处理由于某种原因需要询问订户的情况。我遇到了通过 Web 服务边界的对象的这种需求,其中委托存在问题,而观察者模式只是对另一个对象的引用,因此只要您的序列化保持对象内引用的完整性,它就可以正常工作像 NetDataContractSerializer 一样的图形。在这些情况下,可以根据引用的订阅者是否也在同一个对象图中来区分应该在创建服务边界之前删除的订阅者。

【讨论】:

    【解决方案3】:

    委托可用于实现观察者模式 - 想想事件。

    要在没有事件的情况下执行此操作,请查看此处:http://www.dofactory.com/Patterns/PatternObserver.aspx

    如果您愿意,可以将其重构为使用委托并不需要太多。

    我能想到的实现接口的唯一优势是所有实现中成员名称的一致性。

    【讨论】:

      猜你喜欢
      • 2013-03-11
      • 2010-12-31
      • 2010-09-23
      • 2014-10-14
      • 2016-02-20
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多