【发布时间】:2017-09-17 12:33:18
【问题描述】:
当我在 C# 中使用 Unity 时,我遇到了这个问题。但我认为,对于任何 OOP 语言,对于开始学习设计 OOP 结构以及何时使用观察者模式或发布者-订阅者模式的人来说,这个问题通常都会出现。我具体说的event是the event and delegates in C#。
我正在寻找有关使用事件的建议。我感觉event,或者观察者模式非常有用,以至于我害怕过度使用它。我搜索了这个问题,发现社区建议observer patterns is good to use to receive tweeter feeds 和I 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 observers 和 memory leaks。
讨论似乎表明,当事件的订阅者列表预计在运行时发生变化时,使用观察者模式通常是好的。例如,RSS feeds 在任何给定时间都会有不同的订阅者,程序员无法知道谁在接收它。所以是的,在这里使用观察者模式似乎是一个最佳选择。
但是,我似乎仍然不相信我是否应该赞成使用这种模式,如果开发人员在编译时就知道订阅者列表, 我想进行单元测试。
假设在我的游戏中我的角色正在进入一个新区域。进入新区域后,我希望游戏:
效果列表
- 在屏幕中间显示一个显示
The Swamp of the Code Smell的 GUI - 更新任务板以显示特定于该区域的任务
- 开始降低我角色的每秒 5 点生命值,因为该区域有难闻的气味,并增加 10 点 MP,因为在那里感觉很好
为了实现这一点,我不相信哪种方式是更好的设计模式:
方法 1:将所有信息输入构造函数以进行单元测试
MapEnter 类在其构造函数中有UI、GlobalDamage、Character、...以及所有必需的类。然后它可以调用GlobalDamage.ApplyDamagePerSecond(myCharacter), UI.ShowText(), ...
我之所以这么想是因为a talk about Unit Test 建议类必须是隔离的,这意味着类不能new 任何其他对象,这只能通过其构造函数获得可交互类的列表来实现。
但是,有关如何对观察者模式进行单元测试的帖子建议我可以进行测试以确保 (1) 事件得到良好订阅和取消订阅,以及 (2) 每个要订阅的方法都能独立运行。所以我不太确定这一点。
另一方面,我似乎也相信,当一个类包含其所有引用作为其构造函数中的类变量时,仅通过查看类变量就更容易理解类在多大程度上负责。
现在,当我想扩展MapEnter 的效果时,问题就来了。假设除了我最初计划的三个效果之外,我现在想为其添加一个新功能:
效果列表:
- 开始播放该地区的 BGM
那么现在,我需要更改MapEnter 类的构造函数以了解BgmPlayer。在OnMapEnter() 上更改其实现。更改单元测试用例。以此类推。
这可能会启用Unit Test,但与其他类有很强的联系,因此它似乎具有高耦合度。
方法 2:发布者-订阅者模式
这种方法的一大优点是现在可以非常容易地将任何新想法添加到MapEnter。就像添加代码行以向事件添加/删除方法一样简单。 MapEnter 现在不必担心在其构造函数中使用 N 个参数。
我在这里应用了观察者模式,即使我确切地知道谁将在编译时收听这个事件,这意味着我确实可以在不使用观察者模式的情况下实现这一点。
我的担忧是:
- 这会减少耦合吗?在这种情况下使用观察者模式好不好?
- 方法 1 中的单元测试参数是否证明方法 1 的合理性?
- 如果一个类都引用了它需要调用的内容,就像方法 1 中一样,是否更容易理解代码结构?如果我团队中的其他程序员默默地为
MapEnter的事件添加了新订阅者,如果不查看所有事件的引用,我怎么知道呢? 或者当出现问题时,我是否应该为我的应用程序中的每个事件都这样做?
如果我有理由在这里使用观察者模式,因为它减少了耦合,那么实际上所有方法都可以而且应该通过事件调用其他方法,只要听众不关心谁首先被调用并且没有观察者链。那么这种模式会无处不在,听着看代码even if I ensure there is only 1 or 2 levels of observer chains会很痛苦。
提前致谢。
【问题讨论】:
标签: c# unit-testing oop unity3d design-patterns