2011-10-20 2 views
4

Я искал веские причины, если мы должны попытаться избегать операторов switch/case и как это сделать для перечислений и предложений, как рассмотреть следующий пример: (обратите внимание, что этот переключатель/регистр может быть разбросаны по всей кодовой базе)Записи и заявления о случаях

switch (theEnum) 
{ 
    case MyEnum.Enum1: 
     // dosomething 
    case MyEnum.Enum2: 
     // do something 
    case MyEnum.Enum3: 
     // do something 
    default: 
     throw new Exception("Unsupported enumeration: " + theEnum.ToString()); 

}

VS.

public Dictionary<MyEnum, StrategyBase> BuildMapper() 
{ 
    var mapper = new Dictionary<MyEnum, StrategyBase>(); 
    mapper[MyEnum.Enum1] = new Strategy1(); 
    mapper[MyEnum.Enum2] = new Strategy2(); 
    mapper[MyEnum.Enum3] = new Strategy3(); 
return mapper; 
} 

BuildMapper()[MyEnum.Enum1].DoSomething(); 

Вариант 2 более OO, но мне было интересно, что другие Thi как этот подход, и если есть хорошие и веские причины, по которым мы должны стремиться делать это или нет.

Можно утверждать, что принципы, такие как switch/else, будут нарушать, например, open-close.

+0

Если вы концентрируетесь на сложности Cyclometric, и если методы всегда должны быть расширяемыми, то подход OO лучше. – Zenwalker

+0

Следует отметить, что коммутатор будет выполнять МНОГО быстрее. Прогулка по списку также будет быстрее, чем использование словаря, если в словаре не будет около 10 или более предметов. –

ответ

1

Для OO вы должны использовать Visitor Pattern

+2

Не могли бы вы уточнить, почему * Вместо этого следует использовать шаблон посетителя и погоду, это возможно в качестве замены простых операторов switch/case, так как для них, похоже, немного перехитрить IMHO. –

+0

На самом деле мне нравится эта идея, посетителю может потребоваться дополнительная сантехника, но там, где она лучше по стратегии, стратегия потребует класса для каждого перечисления и каждой операции, где посетитель будет классом для каждого набора операций (проще в обслуживании) – Andre

+0

Существует способ, которым вы можете сделать двойную отправку автоматически с помощью отражения, чтобы отобразить перечисление на метод, con это динамическая природа означает, что компилятор не обнаружит нарушения изменений в перечислении, однако можно, возможно, подойти с атрибутом для представления перечисления на вершине метода, тогда вы получите помощь от компилятора – Andre

0

Я думаю, что первый вариант лучше, потому что он выглядит более понятным и ясным.

1

Я бы сделал BuildMapper статическим (как и для чтения), потому что он всегда будет возвращать вам тот же набор слов.

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

0

Я бы сказал, что все сводится к тому, чего вы хотите достичь. Его легче прочитать первый образец, и это очень важно, если вы делитесь своей базой кода с другими. BuilderMapper может быть полезен, если вы следуете некоторому шаблону.

0

Я думаю, вы сравниваете апельсины и яблоки.

Коммутатор представляет собой последовательное сравнение между переменной и несколькими постоянными данными. Если у вас нет переключателя на 1K, он должен быть намного более эффективным, чем словарь.

Конечно, коммутатор гораздо меньше потребляет память, чем довольно сложный объект, как словарь.

Наконец, перечисления не ограничены объявленными параметрами, но могут быть объединены как «Флаги». Эта функция недоступна, используя хэш-карту.

Удовлетворительно ли это?

+0

Проблема производительности, о которой вы упомянули, является хорошим моментом, но насколько мы говорим 10 микросекунд производительности? я не знаю, но, вероятно, нелюбимый для 99% бизнес-приложений. Использование перечисления как «Флаг» также верно, но всегда можно составить фактическое значение перечисления внутри класса стратегии? – Andre

+0

Это правда. У меня есть два вопроса о вопросе: (1) коммутатор дает вам возможность бесплатно составлять «прыжок» из корпуса в другой, и (2) переключатель является императивным подходом, а хэш-функция является функциональной , Никаких других подсказок! ... –

+0

Извините, я не ответил вам ... базовый тип Enum - целое число. Таким образом, вы можете использовать любую композицию Enums, так как долго вы не будете нарушать безопасность типа. BTW Enum НЕ ЦЕННО! –

1

Я бы пошел за выключателем, если он находится всего в одном или двух местах. Если, как вы говорите, «этот переключатель/регистр может быть разбросан по всей базе кода», тогда перейдите к второму решению.

Это не только больше OO, что хорошо, но проще в вашей ситуации. В этом случае проблемы с производительностью и потреблением памяти совершенно неактуальны, сначала упростите обслуживание, и оптимизируйте их (но я не думаю, что вам когда-нибудь понадобится оптимизировать это).

Также потери чтения в данном случае неактуальны - понимание того, что делает второй подход, занимает очень мало времени.

Смежные вопросы