SOLID & EventAggregator

3
我尽力按照SOLID原则进行编程,但在使用Prism应用程序时遇到了以下问题:
我有一个负责处理模块从其他模块接收的所有事件的类。由于该类具有两个职责(注册处理器和处理事件),我决定将该类分为两个类,这导致我需要将事件处理程序设置为public(这似乎很奇怪)。
在这种情况下,您更喜欢将两个职责放在一个类中还是公开事件处理程序(或其他任何我可能错过的东西)?
谢谢。
public class Handler
{
    public void MethodHandlingAggregatedEvent()
    {
    }
}

public class Register
{
    .... 

    public void RegisterHandler()
    {
        this.eventAggregator.GetEvent<XXX>().Subscribe(this.handler.MethodHandlingAggregatedEvent);
    }
}

1
我不明白为什么你需要将事件处理程序设为公共的。也许你可以提供一些伪代码? - jnovo
@jnovo:如果您在处理事件的类外注册事件,则需要在该类外部创建该方法的委托,因此该方法需要是公共的。添加代码以表示问题。 - Ignacio Soler Garcia
2个回答

3
为了更好地解释我的答案,考虑以下示例:
  • Prism应用程序包含ModuleXModuleY
  • EventAEventB在两个模块都可以访问的某个位置定义。
  • ModuleX包含这两个事件的事件处理程序。
  • ModuleY触发这些事件。

还要考虑SOLID的以下方面(来自Wikipedia

单一职责原则: 一个类应该只有一个职责(即软件规范中只能有一个潜在的变化能够影响类的规范)

接口隔离原则:“客户端不应该依赖它不需要的接口。”[4]

当将您描述的功能映射到此示例时,对其的要求如下:

  1. 为事件A注册处理程序
  2. 为事件B注册处理程序
  3. 处理事件A
  4. 处理事件B

如果您有一个单一的类来处理A和B,那么您将违反单一职责原则。如果您在同一类中定义了一个处理程序并注册了一个事件处理程序,那么您也将违反单一职责原则。

那现在怎么办呢?拆分所有内容将产生四个类,因为这些显然是不同的职责。根据维基百科,SOLID原则存在的目的是简化扩展和修改现有代码;因此,它应该使您的生活更加轻松,而不是更难。

如果我们创建四个类,我们就被迫将事件处理程序代码打开到超出其创建范围的范围之外。在我看来,将事件处理代码以及注册保持在尽可能小的范围内是更好的选择:

class MyHandler
{
    public MyHandler(IEventAggregator eventAggregator)
    {
        eventAggregator.GetEvent<EventA>().Register(HandleEventA);
    }

    private void HandleEventA(EventArgs args)
    {

    }
}

MyHandler现在负责处理EventA。尽管它也在注册处理程序,但仍然可以将其视为事件处理程序的一部分。


我理解你的观点,但是你知道,如果不做例外,生活会更容易,否则每次应用规则时,都必须考虑是否可以在这种情况下应用规则...无论如何,我明白你的意思。我通常把SOLID原则视为我的个人圣经 :) 谢谢。 - Ignacio Soler Garcia

0

我认为你的设计大部分都没问题。

  1. 你的类 Register 负责事件处理程序映射
  2. 每个处理程序负责处理具体事件

我建议将方法 RegisterHandler() 重命名为 RegisterHandlers(),以反映其行为。同时让所有实现接口的类。这样你就可以在单元测试中模拟它们:

_registerMock.Verify(x => x.RegisterHandlers(), Times.Once);

_eventAggregator.Invoke(SomeEvent);
_someHandler.Verify(x => x.MethodHandlingAggregatedEvent(), Times.Once);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接