这种模式出现了很多。它看起来像是一种非常冗长的方式,可以将单独的命名方法移动到单个方法中,然后通过参数进行区分。
有没有什么好的理由让这个模式只有两个方法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");
}
}
答案 0 :(得分:4)
对于OO程序员来说,这看起来很糟糕。
交换机和枚举需要同步维护,默认情况似乎是make-work。
OO程序员会使用命名方法替换对象:然后像method1
这样的名称只会在库中出现一次。此外,所有默认情况都可以避免。
是的,您的客户端仍然需要与您提供的方法同步 - 静态语言始终坚持在编译时知道方法名称。
答案 1 :(得分:2)
您可能会争辩说,此模式允许您将方法入口和退出的共享日志记录(或其他)代码放在一个位置。但我不会。对于这类事情,AOP是一种更好的方法。
答案 2 :(得分:1)
我看不出任何明显的优势。恰恰相反;通过将块拆分为单独的方法,每个方法将更小,更易于阅读和更容易测试。
如果需要,您仍然可以使用相同的“入口点”方法,其中每个案例只会扩展并调用另一个方法。如果不了解具体案例,就不可能说这是好还是坏。无论哪种方式,我肯定会避免在RunCommands
方法中为每个案例实现代码。
答案 3 :(得分:1)
如果只使用名称常量调用RunCommands
,那么我在这种模式中看不到任何优势。
我看到的唯一优势(可能是一个很大的优势)是Method1
和Method2
之间的决定以及实际执行选择的代码可以完全没有关系。当然,当只使用常量来调用RunCommand
时,这种优势就会丢失。
答案 4 :(得分:1)
如果在每个case块内运行的代码是完全独立的,则不添加任何值。但是,如果在参数特定代码之前或之后要执行任何公共代码,则不允许重复该代码。
但是,仍然不是最好的模式。每个单独的方法都可以调用辅助方法来处理公共代码。如果需要进行另一次调用,但是这个不需要前面或末尾的公共代码,整个模型就会被破坏(或者用IF和IF包围该代码)。此时,所有价值都将丢失。
所以,真的,答案是否定的。
答案 5 :(得分:1)
如果您需要非常松散的耦合,那么该模式可能是有效的。例如,您可能有一个界面
interface CommandProcessor{
void process(Command c);
}
如果每个命令都有一个方法,那么每次添加新命令时都需要添加一个新方法,如果你有多个实现,那么你需要将方法添加到每个处理器。这可以通过使用一些基类来解决,但是如果需求有所不同,那么当你添加新的抽象层时,你可能最终会得到一个非常深的类层次(或者你可能已经在处理器中扩展了另一个类。如果它基于切换到常量,您可以拥有默认情况下默认情况下适当处理新案例(异常,无论什么可能适当)。
我在代码中使用了与此类似的模式并添加了工厂。操作从一个小集开始,但我知道它们会增加,所以我有一个机制来描述命令,然后是一个生产CommandProcessors的工厂。工厂将生成适当的处理器,然后该处理器的单个方法将接受该命令并执行其处理。
如果您的命令列表是相当静态的,并且您不需要担心事物的耦合程度,那么每个命令的单一方法方法肯定会使代码更易读。