Замените Enum-переключатель с шаблоном проектирования (IOC) - PullRequest
1 голос
/ 17 июня 2011

У меня есть обработчик событий, который получает объект 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 или хотим изменить способ их обработки, мы должны отрегулировать переключатель, который может стать действительно большим, и я подумывал об использовании чего-то, что позволило бы мне внедрить обработчик для любого данного статуса.

С другой стороны, мне это сейчас не нужно.Решения по коммутаторам работают, но они начинают набирать обороты, поэтому я борюсь между своим ощущением, что это не mantanble и YAGNI.

Существует ли какой-либо шаблон, позволяющий преобразовать коммутаторы такого типа в шаблон IOC?Как вы думаете, мне стоит заняться рефакторингом этого переключателя?

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

Я думаю, что вы можете выполнить рефакторинг по схеме цепочки ответственности .Каждый оператор switch становится объектом-обработчиком в коллекции, которая либо обрабатывает уведомление, либо уведомление передается следующему.

Что касается внедрения, вы сможете изменять количество обработчиков без изменения клиента.код и вставьте mocks / stubs для тестирования.

Чтобы ответить, действительно ли вы должны рефакторинг, нет ничего плохого в самом операторе switch, если он появляется только один раз и остаетсяпросто.Вы захотите провести рефакторинг, если начнете замечать дублирование или другие запахи кода, которые можно исправить с помощью шаблона.

0 голосов
/ 17 июня 2011

Я бы использовал что-то вроде этого:

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!");
     }
}
0 голосов
/ 17 июня 2011

Я хотел бы использовать что-то вроде Abstract Factory pattern.Это очень полезно по отношению к IoC, потому что он может инкапсулировать сложную логику, которая создает другие зависимости.Тогда вы могли бы внедрить свою абстрактную фабрику с помощью инструмента IoC и избавиться от оператора switch.

...