【问题标题】:Do events really make code decoupled?事件真的让代码解耦了吗?
【发布时间】:2014-03-23 23:53:58
【问题描述】:

所以我正在尝试使用事件来解耦我拥有的代码,这是我的问题:

class WorldHandler
{
    public void Notify(object sender, EventArgs e)
    {
        if (e is CameraMovedEventArgs)
        {
            // handle event
        }

        if (e is MapLoaded)
        {
            // handle event
        }
    }
}

WorldHandler 类监听我的应用程序的不同子系统。这不是说 WorldHandler 还与其他子系统耦合吗?直接访问这个类里面的那些子系统不也一样吗?

如果我的问题难以理解,我会在我的帖子中添加更多信息。

我对这个问题进行了研究,但我仍然觉得这很令人困惑,因为不同的人对于如何将代码与事件解耦有非常不同的看法。

【问题讨论】:

    标签: c# .net dependencies decoupling loose-coupling


    【解决方案1】:

    是的,您的代码仍然是耦合的,您不仅可以直接引用类(当您连接事件处理程序时),还可以引用包含正在监视的类的程序集。

    您可以通过在被监视类上使用接口来最小化耦合,并且只能通过接口上公开的项目来访问它。理想情况下,这个接口应该在观察者和被观察者都引用的第三个“更常见”的程序集中。您还可以使用 EventAggregator in Prism 之类的东西来最小化或消除事件耦合。

    耦合本身并不坏,它只是让更换实现和替换它们变得更加困难(或昂贵) - 如果没有适当的解耦,就会有更多的工作和更多的错误风险。您的应用程序可能不需要适当的解耦 - 这取决于您打算如何处理它。

    【讨论】:

    • 你会在同一个程序集中的类之间使用事件吗?
    • @Arjan 每个类都应该独立存在,无论它位于哪个程序集中。因此,如果像值更改事件这样的事件是合适的,那么从事件引发者的角度来看,哪个程序集无关紧要监听器/接收器在。
    • 当然,但事件不是实现类独立的唯一方法,对吧?和事件有缺点。 (例如,当类相互依赖时。事件混淆了这种逻辑)在同一个程序集中,也可以使用接口来实现类独立,那么为什么不使用接口呢?
    • @Arjan 我不明白你的意思——在我的回答中,我已经建议使用接口。 OP 的问题是关于事件的,而您最初的问题是关于事件的,但不知何故您已经偏离了纯粹谈论接口的问题?顺便说一句,接口并不是实现独立或解耦的唯一方法。
    • @Arjan 没问题,我只是想准确地确定您的要求,以便我给出正确的答案。事件不会减少耦合,尽管某些模式(如事件代理)肯定会有所帮助。接口本身也不意味着某些东西是解耦的,它是接口加上依赖注入有帮助。没有一个答案,这就是为什么你在上面找不到 doco。是的,事件会使代码更难测试,因此请考虑使用发布/订阅事件代理,而不是直接注册到事件。
    【解决方案2】:

    使用事件对发生的事情做出反应是解耦。与事件解耦还不错,我建议你这样做。事件的目的是某个类说“我已经完成了”或“我将要这样做”,如果需要,其他类可以对事件做出反应。发送事件的类通常无法知道是否有其他类对它做出反应,除非你当然告诉它。

    【讨论】:

      【解决方案3】:

      解耦不会删除程序所有组件之间的所有依赖关系,你不应该将解耦/耦合与Cohesion混为一谈,松耦合的软件是好的(耦合总是存在的)。

      不过,事件有助于代码解耦,触发事件的源和订阅者是完全不同的独立对象

      【讨论】:

        【解决方案4】:

        一般来说,事件可以帮助您解耦代码,因为对于事件源,所有事件订阅者都是匿名的。换句话说,事件源不需要知道事件接收器。订阅事件的人(不一定是接收器)与源耦合。

        顺便说一句,这不仅适用于 .NET 事件的特殊情况,而且适用于观察者模式等机制,它在 Java 世界中被广泛用于与 .NET 事件相同的目的。

        顺便说一句:如果一个方法不会为所有事件调用相同的操作,那么让一个方法订阅多个事件通常不是一个好主意。更好的方法是使用单独的处理程序方法,例如:

        public void NotifyCameraMoved(object sender, EventArgs e)
        {
            // handle event
        }
        
        
        public void NotifyMapLoaded(object sender, EventArgs e)
        {
            // handle event
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-25
          • 1970-01-01
          • 2014-10-10
          • 1970-01-01
          相关资源
          最近更新 更多