Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果订阅者是预先知道的,我应该使用观察者模式吗?_C#_Unit Testing_Oop_Unity3d_Design Patterns - Fatal编程技术网

C# 如果订阅者是预先知道的,我应该使用观察者模式吗?

C# 如果订阅者是预先知道的,我应该使用观察者模式吗?,c#,unit-testing,oop,unity3d,design-patterns,C#,Unit Testing,Oop,Unity3d,Design Patterns,当我将Unity与C#结合使用时,我遇到了这个问题。但是我认为,对于那些开始学习设计OOP结构的人来说,对于任何OOP语言来说,以及何时使用观察者模式或发布者-订阅者模式,这个问题通常都会出现。我特别提到的事件是 我正在寻找关于使用事件的建议。我觉得事件,或者观察者模式非常有用,以至于我害怕过度使用它。我搜索了这个问题,发现社区提出了这样那样的建议。有一次关于的讨论,建议优先考虑后续事宜。一些人提供了使用观察者模式时需要注意的事项列表,其中常见的有:和 讨论似乎表明,当事件的订阅者列表预计在运行

当我将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参数是否合理