0

我有一个使用命令设计模式的对象集合,即它们实现了一个抽象Command类并有一个execute()方法。

当从命令行调用(例如)时,你可以做这样的事情,但它非常笨重,你将如何实现它:

public void main(String[] arg) {
    Command c = null;

    if(arg[0].equals("FirstCommand") {
        c = new FirstCommand(arg[1]);
    }
    if(arg[0].equals("SecondCommand") {
        c = new SecondCommand(arg[1], arg[2]);
    }
    if(arg[0].equals("ThirdCommand") {
        c = new ThirdCommand(arg[1], Long.parseLong(arg[2]));
    }
    //.....etc....
    c.execute();
}

显然,随着可用命令列表的增加,这将成为相当乏味的代码

4

2 回答 2

1

反思很容易。从这个开始:

final Class[] argTypes = new Class[args.length - 1];
final String[] cmdArgs = new String[args.length - 1];
for (int i = 0; i < argTypes.length; i++) {
  argTypes[i] = String.class;
  cmdArgs[i] = args[i+1];
}
final Command c = (Command) Class.forName(MY_PACKAGE + args[0]).getConstructor(argTypes)
   .newInstance(cmdArgs);

现在,唯一要解决的问题是您将不得不将解析和验证推送到您的Command构造函数中。或者,如果你想变得花哨,你可以找到一个仅基于 arg count 的构造函数,查看它接受的 arg 类型,并适当地解析 cmdline args。

于 2012-04-12T13:21:46.617 回答
0

不需要您跟踪可用命令的通用解决方案是使用反射来实例化命令。您要么有一个带有参数列表的构造函数,要么像 McDowell 建议的那样定义执行方法。这取决于您是否要使用相同的参数多次重新执行相同的命令,以及命令是否可以从缓存的结果中受益(无状态与有状态)。

命令名称将是类的简单名称。您只需添加包以创建一个完全限定的名称,然后 class.getConstructor(Class[] params) 并调用该构造函数(或者如果您选择将参数传递给执行方法,则使用默认构造函数)。

于 2012-04-12T12:25:11.140 回答