1

我有一个事件处理程序,它接收一个 eventargs 对象,该对象是一个枚举值,可以进一步细化里面的信息。它看起来像

public enum StatusCallbackType { Status1, Status2, Status3, Status4 }

public class StatusEventArgs
{
  public StatusCallbackType Type {get;set;}
  public StatusData Data {get; set;}
}

Statusdata 是一个基础抽象类,它根据给定的 CalllbackType 进行更改。

现在处理事件的代码看起来类似于

switch e.Type
{
  case Status1:
    DoAction1(e.Data as Opt1Data);
    break;
  case Status2:
    DoAction1(e.Data as Opt2Data);
    break;
  case Status3:
    DoAction1(e.Data as Opt3Data);
    break;
}

问题是,如果我们更改 StatusNotifications 或想要更改它们的处理方式,我们必须调整可能变得非常大的开关,我正在考虑使用允许我为任何给定状态注入处理程序的东西。

另一方面,我现在真的不需要它。交换机解决方案有效,但它开始变大,所以我在我认为它不可维护和 YAGNI 之间进行斗争。

是否有任何模式可以将这种开关转换为 IOC 模式?你认为我真的应该费心重构那个开关吗?

4

3 回答 3

2

我认为您可以重构为责任链模式。每个 switch 语句都成为集合中的一个处理程序对象,该对象要么处理通知,要么将通知传递给下一个。

至于注入,您将能够在不修改客户端代码的情况下改变处理程序的数量并注入模拟/存根进行测试。

要回答是否应该重构,switch 语句本身没有问题,只要它只出现一次并且保持简单。如果您开始注意到可以通过模式修复的重复或其他代码异味,您将需要重构。

于 2011-06-17T11:05:19.350 回答
0

我可能会使用这样的东西:

public interface IStatusHandler
{
    bool Handle(StatusData statusData);
}

public class Status1Handler : IStatusHandler
{
    public bool Handle(StatusData statusData)
    {
        if (statusData as Opt1Data == null) return false; // you don't need Type anymore

        ...

        return true;
    }
}

public class StatusManager
{
     private IList<IStatusHandler> handlers;

     public StatusManager(IList<IStatusHandler> handlers) // inject with IoC here
     {
         this.handlers = handlers;
     }

     public void ProcessStatus(StatusEventArgs args)
     {
         foreach(var handler in handlers)
             if (handler.Handle(args.Data)) return;

         throw new Exception("No handler for this kind of status!");
     }
}
于 2011-06-17T12:48:09.363 回答
0

我会考虑使用抽象工厂模式之类的东西。它对于 IoC 非常有用,因为它可以封装创建其他依赖项的复杂逻辑。然后,您可以使用 IoC 工具注入您的抽象工厂并摆脱 switch 语句。

于 2011-06-17T11:01:23.813 回答