【问题标题】:Substitute Enum switch with design pattern (IOC)使用设计模式 (IOC) 替换 Enum 开关
【发布时间】:2011-06-17 10:51:43
【问题描述】:

我有一个事件处理程序,它接收一个 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 模式?你认为我真的应该费心重构那个开关吗?

【问题讨论】:

  • 这可能更好地位于 codereview.stackexchange.com

标签: c# design-patterns refactoring switch-statement yagni


【解决方案1】:

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

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

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

【讨论】:

  • 你能举个例子吗
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    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!");
         }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多