2012-04-12 87 views
0

我有一个使用command design pattern的对象集合,即它们实现了一个抽象Command类,并且有一个​​方法。使用命令设计模式将命令行参数转换为对象

调用时(例如)在命令行中,你可以做这样的事情,但其严重笨重,你将如何实现这一点:

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(); 
} 

显然可用命令的列表的增长,这变得相当繁琐的代码

回答

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。

0

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

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

+0

这是我的理解,它不可能做到这一点没有一些复杂的类路径加载hackery? – Jacob 2012-04-12 12:30:04

+0

你认为classpath hackery是什么意思?我的答案假定指定为参数的类可用于正在运行的类的类加载器。 Marko TopoInik发布了我懒得写出答案的代码 – bennidi 2012-04-27 20:42:28