C# 如果订阅者是预先知道的,我应该使用观察者模式吗?
当我将Unity与C#结合使用时,我遇到了这个问题。但是我认为,对于那些开始学习设计OOP结构的人来说,对于任何OOP语言来说,以及何时使用观察者模式或发布者-订阅者模式,这个问题通常都会出现。我特别提到的C# 如果订阅者是预先知道的,我应该使用观察者模式吗?,c#,unit-testing,oop,unity3d,design-patterns,C#,Unit Testing,Oop,Unity3d,Design Patterns,当我将Unity与C#结合使用时,我遇到了这个问题。但是我认为,对于那些开始学习设计OOP结构的人来说,对于任何OOP语言来说,以及何时使用观察者模式或发布者-订阅者模式,这个问题通常都会出现。我特别提到的事件是 我正在寻找关于使用事件的建议。我觉得事件,或者观察者模式非常有用,以至于我害怕过度使用它。我搜索了这个问题,发现社区提出了这样那样的建议。有一次关于的讨论,建议优先考虑后续事宜。一些人提供了使用观察者模式时需要注意的事项列表,其中常见的有:和 讨论似乎表明,当事件的订阅者列表预计在运行
事件是
我正在寻找关于使用事件的建议。我觉得事件
,或者观察者模式非常有用,以至于我害怕过度使用它。我搜索了这个问题,发现社区提出了这样那样的建议。有一次关于的讨论,建议优先考虑后续事宜。一些人提供了使用观察者模式时需要注意的事项列表,其中常见的有:和
讨论似乎表明,当事件的订阅者列表预计在运行时更改时,通常最好使用观察者模式。例如,RSS提要
在任何给定时间都有不同的订户,程序员无法知道谁在接收它。因此,是的,在这里使用观察者模式似乎是个不错的选择
然而,我似乎仍然不确定是否应该使用这种模式,如果开发人员在编译时知道订户列表,并且我想执行单元测试
假设在我的游戏中,我的角色正在进入一个新的领域。进入新区域后,我希望游戏:
效果表
在屏幕中部 显示代码>代码>代码气味>代码>
更新任务板以显示特定于此区域的任务
开始降低我的角色每秒的血量5,因为这个区域有异味,增加MP 10,因为在那里感觉很好
为了实现这一点,我不确定哪种方式是更好的设计模式:
方法1:将所有信息输入到构造函数中进行单元测试
MapEnter
类具有UI
,GlobalDamage
,字符
。。。以及其构造函数中所有必需的类。然后它就可以调用GlobalDamage.ApplyDamagePerSecond(myCharacter)
,UI.ShowText()
我这样想是因为suggsted类必须被隔离,这意味着类不能new
任何其他对象,而这只能通过其构造函数提供可交互类的列表来实现
然而,关于如何对观察者模式进行单元测试的帖子表明,我可以进行测试,以确保(1)事件得到良好的订阅和取消订阅,以及(2)订阅的每个方法都能独立运行。所以我不太确定这一点
另一方面,我似乎也相信,当一个类包含它的所有引用作为它的构造函数中的类变量时,仅仅通过查看类变量就更容易理解一个类负责的程度
现在,当我想扩展MapEnter
的效果时,问题来了。比如说,除了我最初计划的三种效果之外,我现在还想添加一个新功能:
效果列表:
开始播放该区域的背景音乐
现在,我需要更改MapEnter
类的构造函数以了解bgmlayer
。在OnMapEnter()
上更改其实现。更改单元测试用例。等等等等
这可以启用单元测试
,但与其他类紧密相连,因此它似乎具有高耦合性
方法2:发布者-订阅者模式
这种方法的一大优点是,现在向MapEnter
添加任何新想法都非常容易。向事件添加/删除方法与添加代码行一样简单MapEnter
现在不必担心在其构造函数中获取N个参数
在这里,我应用了观察器模式,尽管我确切地知道谁将在编译时监听这个事件,这意味着我确实可以在这里不使用观察器模式实现这一点
我关注的是:
这会减少耦合吗?在这种情况下使用观察者模式好吗
方法1中的单元测试参数是否证明了方法1的合理性
如果一个类像方法1中那样拥有对它需要调用的对象的所有引用,那么理解代码结构不是更容易吗?如果我的团队中的其他程序员悄悄地向MapEnter
事件添加了新订阅者,那么如果不查看所有事件的引用,我怎么知道还是当出现问题时,我应该为应用程序中的每个事件都这样做?
如果我有理由在这里使用观察者模式,因为它减少了耦合,那么实际上所有方法都可以而且应该通过事件调用其他方法,只要侦听器不关心谁首先被调用,并且没有观察者链。然后这种模式将无处不在,这听起来理解代码会很痛苦
提前感谢。决定取决于您的情况,我认为理解《观察家》和《出版商/订户模式》之间的区别很重要
主要是以同步的方式实现的,当某个事件发生时,可观察对象调用其所有观察者的适当方法。发布者/订阅者模式主要以异步方式实现(通过消息队列)
在观察者/可观察模式中,观察者意识到可观察。然而,在发布者/订阅者中,发布者和订阅者不需要相互了解。它们只需借助消息队列进行通信。感谢您指出这两种模式之间的差异。然而,我更关心的是,将所有信息输入co参数是否合理