命令模式与反射

时间:2014-11-21 06:55:02

标签: java design-patterns reflection command-pattern

我有控制器根据命令名执行一些命令,取自url。重点是不使用if和switch子句。据我所知,只有两种方法可以做到 - 1)命令模式2)反射。

//Command pattern
class Controller{
  private HashMap<String,Command> commands;
  public void executeCommand(String commandName){
    commands.get(commandName).execute();
  }
  ...
}

//reflection
class Controller{
  public void readCommand(){
    ....
  }
  public void executeCommand(String commandName){
    this.getClass().getMethod(commandName+"Command").invoke(this);
  }
  ...
}

所以问题:

  1. 哪一个更好?
  2. 在一个应用程序中让开发人员使用他们想要的方法之一是否正常。
  3. 还有其他方法吗?

3 个答案:

答案 0 :(得分:4)

  1. 第一种方式更好,只有在没有其他选择时才使用反射。
  2. 在一个应用程序中应该有一种方法来解决一种问题。
  3. 我认为第一种方法很好。 (比if / else阻止好多了)

答案 1 :(得分:1)

  

哪一个更好?

显然,第一个更好。即使你引用了你正在使用命令模式,它也不完整&#34; Command&#34;图案。 命令模式将具有Command(抽象),具体命令,接收器,调用者和客户端

看看这个问题:

Using Command Design pattern

除了Command Patten之外,我想强调反思的利弊。

<强> 优点:

  1. 处理依赖注入
  2. 开发即插即用框架
  3. <强> 缺点:

    1. 反射调用较慢
    2. 您可能违反安全性并以不良意图爆炸应用程序(例如,设置类的私有变量,这对其他类是不可见的)
    3. 查看有关反思的相关SE问题:

      What is reflection and why is it useful?

        

      在一个应用程序中让开发人员使用他们想要的方法之一是否正常。

      开发人员选择最佳方法解决特定问题是正常的。

        

      还有其他方法吗?

      这取决于您要解决的问题类型。设计模式为重复出现的问题提供了解决方案。

      所有解决方案都不适合现有的设计模式。您可能已经开发出新的模式来解决您的问题。

答案 2 :(得分:0)

我认为您的第一种方法有两种不同的方式。每个命令都可以是抽象类Command的子类。或者每个命令可以是类命令的实例。这取决于所有应该是多么灵活,并且是命令的参数和返回值?对于子类,它看起来像这样(只是为了得到这个想法):

abstract public class Command {
    abstract public void execute();
}

public class LsCommand extends Command
{
    @Override
    public void execute() {
        try {
            Runtime.getRuntime().exec("ls");
        } catch (IOException e) {}
    }
}

public class ChdirCommand extends Command
{
    @Override
    public void execute() {
        try {
            Runtime.getRuntime().exec("chdir");
        } catch (IOException e) {}
    }
}

我的回答是:

  1. 你的第一种方式更好。总是喜欢设计模式 反射。
  2. 对不起,我不明白问题2.但它无论如何都没有问号,所以我只是跳过它:)
  3. 您可能希望查看Strategy design pattern,其中每个命令甚至可以由子命令的不同部分组成。 另一个想法是Factory design pattern。在那种情况下你 将每个命令放入一个类,然后使用ClassLoader 按名称加载类。