如果提前知道订阅者,我应该使用观察者模式吗?

时间:2017-04-20 18:11:40

标签: c# unit-testing oop unity3d design-patterns

当我在C#中使用Unity时,我遇到了这个问题。但是我认为对于那些开始学习设计OOP结构以及何时使用观察者模式或发布者 - 订阅者模式的人来说,任何OOP语言都可能出现这个问题。我专门讨论的eventthe event and delegates in C#

我正在寻找有关使用活动的建议。我感觉event,或观察者模式是如此有用,以至于我害怕过度使用它。我搜索了这个问题,发现社区建议observer patterns is good to use to receive tweeter feedsI should use the Observer Pattern if and only if using the pattern will reduce coupling。对when design patterns should be avoided进行了讨论,建议优先关注the SOLID principle。有些人提供了使用观察者模式时需要注意的事项列表,其中常见的有:chains of observersmemory leaks

讨论似乎表明,当事件的订阅者列表在运行时发生变化时,通常可以使用观察者模式。例如,RSS feeds在任何给定时间都会有不同的订阅者,并且程序员无法知道谁正在接收它。所以,在这里使用观察者模式似乎是个好地方。

但是,我仍然不相信我是否应该支持使用这种模式, 如果开发人员在编译时知道订阅者列表 ,和 我想执行单元测试

让我们在游戏中说我的角色正在进入一个新区域。进入一个新区域后,我希望游戏:

效果列表

  1. 在屏幕中间显示一个说明The Swamp of the Code Smell的GUI
  2. 更新Quest Board以显示特定于此区域的任务
  3. 开始减少我的角色的每秒HP 5,因为该区域有难闻的气味并且将MP增加10,因为感觉很好在那里
  4. 为实现这一目标,我不相信哪种方式是更好的设计模式:

    方法1:将所有信息输入构造函数以进行单元测试

    MapEnter类包含UIGlobalDamageCharacter,...以及构造函数中所有必需的类。然后,它可以调用GlobalDamage.ApplyDamagePerSecond(myCharacter)UI.ShowText(),...

    我想到了这种方式,因为a talk about Unit Test的构造类必须被隔离,这意味着类不能new任何其他对象,并且这只能通过给出可交互类的列表来实现构造

    然而,关于如何单元测试观察者模式的帖子建议我可以测试以确保(1)事件得到良好的订阅和取消订阅,以及(2)每个要订阅的方法都是独立的。所以我对这一点不太确定。

    另一方面,我似乎也相信当一个类包含其所有引用作为其构造函数的类变量时,通过查看类更容易理解一个类的负责程度类变量。

    现在,当我想扩展MapEnter的效果时问题就出现了。让我们说除了我最初计划的三个效果之外,我现在想要为它添加一个新功能:

    效果清单:

    1. 开始播放该区域的背景音乐
    2. 然后现在,我需要更改MapEnter类的构造函数以了解BgmPlayer。在OnMapEnter()更改其实施。改变单元测试用例。依此类推。

      这可能会启用Unit Test但与其他类强关联,因此它似乎具有高耦合。

      方法2:发布者 - 订阅者模式

      这种方法的一大优点是,现在向MapEnter添加任何新想法非常容易。添加/删除事件的方法就像添加代码行一样简单。 MapEnter现在无需担心在其构造函数中使用N个参数。

      这里我应用了观察者模式,即使我确切地知道谁会在编译时听这个事件,这意味着我确实可以在不使用观察者模式的情况下实现这一点。

      我担心的是:

      1. 这会减少耦合吗?在这种情况下使用观察者模式是否合适?
      2. 方法1中的单元测试参数是否证明方法1的合理性?
      3. 如果一个类在方法1中具有所需的所有引用,那么理解代码结构会更容易吗?如果我团队中的其他程序员默默地将新订阅者添加到MapEnter的事件中,那么如果不经历所有事件的引用,我怎么知道呢? 或者当出现问题时我是否应该为应用程序中的每个事件执行此操作?
      4. 如果我有理由在这里使用观察者模式,因为它减少了耦合,实际上所有方法都可以并且应该通过事件调用其他方法,只要监听器不关心谁先被调用而且没有观察者链。然后这种模式将无处不在,听起来理解代码even if I ensure there is only 1 or 2 levels of observer chains会很痛苦。

        提前致谢。

1 个答案:

答案 0 :(得分:0)

决定取决于您的情况,我认为理解差异观察者和发布者/订阅者模式很重要。

Observer主要以同步方式实现,当某个事件发生时,observable调用其所有观察者的适当方法。发布者/订阅者模式主要以异步方式实现(通过消息队列)。

在Observer / Observable模式中,观察者知道可观察的。然而,在发布者/订阅者中,发布者和订阅者不需要彼此了解。他们只是在消息队列的帮助下进行通信。