【问题标题】:Using switch and enumerations as substitute for named methods使用 switch 和枚举代替命名方法
【发布时间】:2010-03-22 15:12:48
【问题描述】:

这种模式经常出现。这看起来像是一种非常冗长的方法,可以将原本单独的命名方法移动到单个方法中,然后通过参数进行区分。

是否有充分的理由让这种模式超过只有两个方法 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");
    }
}

【问题讨论】:

    标签: c# java design-patterns switch-statement


    【解决方案1】:

    对于 OO 程序员来说,这看起来很可怕。

    switch 和 enum 需要同步维护,默认情况下看起来像是做工。

    OO 程序员会用命名方法替换一个对象:然后像method1 这样的名称只会在库中出现一次。此外,所有默认情况都将被排除。

    是的,您的客户端仍然需要与您提供的方法同步 - 静态语言始终坚持在编译时知道方法名称。

    【讨论】:

    • +1 我相信您正在描述策略模式。通常可以引入它来减少这种切换。
    【解决方案2】:

    您可能会争辩说,这种模式允许您将用于方法进入和退出的共享日志记录(或其他)代码放在一个地方。但我不会。对于这类事情,AOP 是一种更好的方法。

    【讨论】:

      【解决方案3】:

      如果您需要非常松散的耦合,该模式可能是有效的。例如你可能有一个接口

      interface CommandProcessor{
        void process(Command c);
      }
      

      如果每个命令都有一个方法,那么每次添加新命令时都需要添加新方法,如果有多个实现,则需要将方法添加到每个处理器。这可以通过拥有一些基类来解决,但是如果需求不同,当您添加新的抽象层时,您最终可能会得到一个非常深的类层次结构(或者您可能已经在使用处理器扩展另一个类。如果它基于切换常量,您可以让默认情况下适当地处理新情况(例外,任何可能合适的情况)。

      我在代码中使用了与此类似的模式,并添加了工厂。这些操作从一个小集合开始,但我知道它们会增加,所以我有一个描述命令的机制,然后是一个生产 CommandProcessors 的工厂。工厂将生成适当的处理器,然后该处理器的单一方法将接受命令并执行其处理。

      也就是说,如果您的命令列表是相当静态的,并且您不需要担心事物之间的耦合程度,那么每个命令一个方法的方法当然更适合编写更具可读性的代码。

      【讨论】:

      • 我同意,这似乎更适合使用命令模式。
      【解决方案4】:

      我看不到任何明显的优势。恰恰相反;通过将块拆分为单独的方法,每个方法将更小、更易于阅读和更易于测试。

      如果需要,您仍然可以使用相同的“入口点”方法,其中每个案例都会分支出来并调用另一个方法。如果不了解更多具体案例,就不可能说这是一个好主意还是坏主意。不管怎样,我肯定会避免在 RunCommands 方法中为每个案例实现代码。

      【讨论】:

        【解决方案5】:

        如果 RunCommands 只使用名称常量调用,那么我根本看不出这种模式有任何优势。

        我看到的唯一优势(而且可能很大)是Method1Method2 之间的决定与实际执行该选择的代码可能完全不相关。当然,当只使用常量调用RunCommand 时,这种优势就会丧失。

        【讨论】:

          【解决方案6】:

          如果在每个 case 块中运行的代码是完全独立的,则没有附加值。但是,如果在参数特定代码之前或之后有任何公共代码要执行,这允许它不会重复。

          不过,仍然不是最好的模式。每个单独的方法都可以调用辅助方法来处理公共代码。如果需要另一个调用,但 this 不需要前面或末尾的公共代码,则整个模型被破坏(或者你用和 IF 包围该代码)。此时,所有价值都将丢失。

          所以,真的,答案是否定的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-02
            • 2011-08-08
            • 2012-04-30
            • 2017-12-13
            相关资源
            最近更新 更多