我正在为一个Z80模拟器编写调试器,我们正在学校项目中使用Java编写。调试器从用户读取命令,执行它,读取另一个命令等。
命令可以是较少的参数,具有可选参数,也可以使用无限量的参数。参数主要是整数,但偶尔它们是字符串。
目前,我们正在使用Scanner-class来读取和解析输入。 The read-method looks kinda like like this (I'm writing this off the top of my head, not paying attention to syntax nor correctness).
这是在项目开始时写的一个kludge,当我们向调试器添加越来越多的命令时,它很快就失控了。
我对这段代码的主要问题是大量的重复,if / else-nestedness的高级别以及整个丑陋。
我想建议如何使这个代码更美观和模块化,以及哪种模式适合这种程序。
我还想了解更多有关代码风格的一般建议。
答案 0 :(得分:2)
是的,有一种更简单/更好的方法,特别是在Java或其他OO语言中。
首先,基本的见解是你的命令解析器是一个有限状态机:START状态是一个空行(或一行开头的索引)。
让我们考虑echo
:
$ echo foo bat "bletch quux"
将该行标记为多个部分:
“echo”“foo”“bar”“bletch quux”
在shell中,语法通常是动词名词名词名词...... 所以这样解释它。你可以使用if-else序列来完成它,但哈希更好。您使用字符串作为索引加载哈希,并索引其他内容。它可能只是一个数字,它将进入一个开关:
(这是伪代码):
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
}
更好的是,您可以应用命令和对象工厂模式。现在你有一个类Command
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());
对象。
答案 1 :(得分:1)
您是否考虑过使用地图进行调度?一个hashmap很容易放在那里。只需将密钥作为命令,然后创建一个接口或抽象类,它就是这样的命令:
interface Commmand {
void execute(String args);
}
或者更好的是你可以事先砍掉论据:
interface Commmand {
void execute(String[] args);
}
然后你会使用HashMap< String,Command>。