是的,有一种更简单/更好的方法,尤其是在 Java 或其他 OO 语言中。
首先,基本见解是您的命令解析器是一个有限状态机:START 状态是一个空行(或行首的索引)。
让我们想想echo
:
$ echo foo bat "bletch quux"
将行标记为碎片:
“回声”“富”“酒吧”“bletch quux”
在外壳中,语法通常是动词名词名词......所以这样解释。您可以使用一系列 if-else if 来实现,但哈希更好。您使用字符串作为索引加载哈希,并索引其他内容。它可能只是一个数字,它会进入一个开关:
(这是伪代码):
Hashtable cmds = new Hashtable();
enum cmdindx { ECHO=1, LS=2, ...}
cmds.add("echo", ECHO); // ...
// get the token into tok
switch (cmds.get(tok)) {
case ECHO: // process it
// get each successor token and copy it to stdout
break;
...
default:
// didn't recognize the token
// process errors
}
更好的是,您可以应用命令和对象工厂模式。现在你有一个类命令
public interface Command {
public void doThis(String[] nouns) ;
public Command factory();
}
public class Echo implements Command {
public void doThis(String[] nouns){
// the code is foreach noun in nouns, echo it
}
public Command factory(){
// this clones the object and returns it
}
}
现在,您的代码变为
// Load the hash
Hashtable cmds = new Hashtable();
cmds.add("echo", new Echo()); // one for each command
// token is in tok
// the "nouns" or "arguments are in a String[] nouns
((cmds.get(tok)).factory()).doThis(nouns);
看看这是如何工作的?您在哈希中查找对象。您调用该factory
方法来获取新副本。doThis
然后,您使用该方法调用该命令的处理。
更新
这可能有点太笼统了,因为它使用了工厂模式。为什么要有工厂方法?主要是,您将使用它,以便每次执行命令时,“动词”对象(如 的实例Echo
)都可以拥有自己的内部状态。如果您不需要状态持续很长时间,您可以将其简化为
(cmds.get(tok)).doThis(nouns);
现在它只是获取并使用Echo
您在实例化它时创建的对象cmds.add("echo", new Echo());
。