Использование переключателя и перечислений в качестве замены именованных методов - PullRequest
1 голос
/ 22 марта 2010

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

Есть ли веская причина для использования этого шаблона, просто имея два метода Method1 ()и Method2 ()?Настоящим ударом является то, что этот шаблон обычно вызывается только с константами во время выполнения, то есть все аргументы известны до того, как компиляция завершена.

public enum Commands
{
    Method1,
    Method2
}

public void ClientCode()
{
    //Always invoked with constants! Never user input.
    RunCommands(Commands.Method1);
    RunCommands(Commands.Method2);
}

public void RunCommands(Commands currentCommand)
{
    switch (currentCommand)
    {
        case Commands.Method1:
            // Stuff happens
            break;
        case Commands.Method2:
            // Other stuff happens
            break;
        default:
            throw new ArgumentOutOfRangeException("currentCommand");
    }
}

Ответы [ 6 ]

4 голосов
/ 22 марта 2010

Для программиста OO это выглядит ужасно.

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

Программист OO заменит объект именованными методами: тогда имена, подобные method1, будутпоявляются один раз в библиотеке.Также будут исключены все случаи по умолчанию.

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

2 голосов
/ 22 марта 2010

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

1 голос
/ 22 марта 2010

Этот шаблон может быть действительным, если вам нужно, чтобы муфта была очень слабой. Например, у вас может быть интерфейс

interface CommandProcessor{
  void process(Command c);
}

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

Я использовал шаблон, подобный этому, в моем коде с добавлением фабрики. Операции начинались как небольшой набор, но я знал, что они будут увеличиваться, поэтому у меня был механизм для описания команды, а затем фабрика, которая производила CommandProcessors. Фабрика сгенерирует соответствующий процессор, а затем единственный метод этого процессора примет команду и выполнит ее обработку.

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

1 голос
/ 22 марта 2010

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

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

так что, действительно, ответ - нет.

1 голос
/ 22 марта 2010

Если RunCommands вызывается только с константами имен, то я не вижу никакого преимущества в этом шаблоне.

Единственное преимущество, которое я вижу (и оно может иметь большое значение), заключается в том, что решение между Method1 и Method2 и кодом, который на самом деле выполняет , выбор может быть совершенно не связан. Конечно, это преимущество теряется, когда для вызова RunCommand.

используются только константы.
1 голос
/ 22 марта 2010

Я не вижу никаких очевидных преимуществ. Наоборот; разделив блоки на отдельные методы, каждый метод будет меньше по размеру, его легче будет читать и легче тестировать.

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

...