8

我正在使用 Java 为我们在学校项目中编写的 Z80 模拟器编写调试器。调试器从用户那里读取一个命令,执行它,读取另一个命令,等等。

命令可以是更少参数,具有可选参数,或者采用无限数量的参数。参数大多是整数,但有时它们是字符串。

目前,我们使用 Scanner 类来读取和解析输入。read-method 看起来有点像这样(我是在脑海中写下这个,没有注意语法和正确性)。

这是在项目开始时编写的一个杂物,随着我们向调试器添加越来越多的命令,它很快就失控了。

我对这段代码的主要问题是大量的重复、高级别的 if/else 嵌套以及周围的丑陋。

我想就如何使这段代码更漂亮和模块化,以及什么样的模式适合这种程序提出建议。

我还想对代码风格提出更一般的建议。

4

2 回答 2

2

是的,有一种更简单/更好的方法,尤其是在 Java 或其他 OO 语言中。

首先,基本见解是您的命令解析器是一个有限状态机:START 状态是一个空行(或行首的索引)。

让我们想想echo

$ echo foo bat "bletch quux"
  1. 将行标记为碎片:

    “回声”“富”“酒吧”“bletch quux”

  2. 在外壳中,语法通常是动词名词名词......所以这样解释。您可以使用一系列 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());

于 2009-04-04T19:17:36.807 回答
1

您是否看过使用地图进行调度?一个hashmap很容易放在那里。只需将键设置为命令并创建一个接口或抽象类,它是这样的命令:

interface Commmand {
   void execute(String args);
}

或者更好的是,您可以提前切碎论点:

interface Commmand {
   void execute(String[] args);
}

然后你会使用 HashMap<String,Command>。

于 2009-04-04T19:12:11.000 回答