C# 使用开关和枚举替换命名方法
这种模式经常出现。这看起来像是一种非常冗长的方式,将原本单独命名的方法移动到单个方法中,然后通过参数进行区分 有没有什么好的理由让这种模式超越两个方法Method1()和Method2()?真正重要的是,这种模式往往在运行时仅使用常量调用——即,在编译完成之前,参数都是已知的C# 使用开关和枚举替换命名方法,c#,java,design-patterns,switch-statement,C#,Java,Design Patterns,Switch Statement,这种模式经常出现。这看起来像是一种非常冗长的方式,将原本单独命名的方法移动到单个方法中,然后通过参数进行区分 有没有什么好的理由让这种模式超越两个方法Method1()和Method2()?真正重要的是,这种模式往往在运行时仅使用常量调用——即,在编译完成之前,参数都是已知的 public enum Commands { Method1, Method2 } public void ClientCode() { //Always invoked with constan
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");
}
}
您可能会争辩说,这种模式允许您将方法入口和出口的共享日志(或其他)代码放在一个地方。但我不会。AOP是解决这类问题的一种更好的方法。您可以说,这种模式允许您将用于方法进入和退出的共享日志(或其他)代码放在一个地方。但我不会。AOP是解决这类问题的更好方法。我看不出有任何明显的优势。恰恰相反;通过将块拆分为单独的方法,每个方法都将更小、更易于阅读和测试
如果需要,您仍然可以使用相同的“入口点”方法,其中每个案例只需分支并调用另一个方法。在不了解更多具体案例的情况下,很难说这是个好主意还是个坏主意。无论哪种方法,我都绝对不会在
RunCommands
方法中实现每种情况下的代码。我看不到任何明显的优势。恰恰相反;通过将块拆分为单独的方法,每个方法都将更小、更易于阅读和测试
如果需要,您仍然可以使用相同的“入口点”方法,其中每个案例只需分支并调用另一个方法。在不了解更多具体案例的情况下,很难说这是个好主意还是个坏主意。无论哪种方式,我都绝对不会在
RunCommands
方法中实现每种情况下的代码。如果RunCommands
只使用names常量调用,那么我看不到这种模式的任何优势
我看到的唯一优势(这可能是一个很大的优势)是
Method1
和Method2
之间的决定与实际执行选择的代码可能完全无关。当然,这一优势已经丧失,当只有常量被用来调用RunCommand
时,如果RunCommands
仅被命名为常量调用,那么我看不到这一模式的任何优势
我看到的唯一优势(这可能是一个很大的优势)是
Method1
和Method2
之间的决定与实际执行选择的代码可能完全无关。当然,如果在每个case块中运行的代码是完全独立的,则仅使用常量调用RunCommand
时,这种优势就丧失了。但是,如果在参数特定代码之前或之后要执行任何公共代码,则允许不重复该代码
不过,这仍然不是最好的模式。每个单独的方法只能调用helper方法来处理公共代码。如果需要另一个调用,但是这个调用不需要前面或后面的公共代码,那么整个模型都会被破坏(或者用and if来包围代码)。此时,所有值都将丢失
因此,事实上,答案是否定的。如果在每个case块中运行的代码是完全独立的,则没有任何附加值。但是,如果在参数特定代码之前或之后要执行任何公共代码,则允许不重复该代码 不过,这仍然不是最好的模式。每个单独的方法只能调用helper方法来处理公共代码。如果需要另一个调用,但是这个调用不需要前面或后面的公共代码,那么整个模型都会被破坏(或者用and if来包围代码)。此时,所有值都将丢失
所以,事实上,答案是否定的。对于OO程序员来说,这看起来很可怕 交换机和enum需要同步维护,默认情况下似乎可以正常工作 OO程序员会用命名方法替换对象:然后像
method1
这样的名称在库中只出现一次。此外,所有违约案例都将被排除
是的,您的客户机仍然需要与您提供的方法同步-静态语言总是坚持在编译时知道方法名称。对于OO程序员来说,这看起来很可怕 交换机和enum需要同步维护,默认情况下似乎可以正常工作 OO程序员会用命名方法替换对象:然后像
method1
这样的名称在库中只出现一次。此外,所有违约案例都将被排除
是的,您的客户机仍然需要与您提供的方法同步-静态语言始终坚持方法名称在编译时已知。如果您需要非常松散的耦合,则该模式可能有效。例如,您可能有一个接口
interface CommandProcessor{
void process(Command c);
}
如果每个命令都有一个方法,那么每次添加新命令时都需要添加一个新方法;如果有多个实现,则需要将该方法添加到每个处理器。这可以通过使用一些基类来解决,但是如果需求发生分歧,那么在添加新的抽象层时,最终可能会有一个非常深的类继承权(或者您可能已经在使用处理器扩展中的另一个类。如果它基于switch的over the常量,则您可以使用默认情况,在默认情况下适当地处理新情况(异常,任何适当的情况)
我在代码中使用了类似的模式,添加了一个工厂。操作开始时是一个小集合,但我知道它们会增加,s