从控制台验证用户输入。命令是否有效等

时间:2013-01-15 08:00:47

标签: java design-patterns data-structures io console

当程序从控制台获取命令时,验证命令是否有效并执行它的标准/最佳实践是什么?
我在想像HashMap<String,Object>这样的东西,但这不会降低所有字符串比较的性能吗?

3 个答案:

答案 0 :(得分:2)

首先,不要担心性能。时间会更晚(或者更有可能,根本不会发生)。解析命令不会比执行命令花费更多时间,是吗?

至于处理命令:首先,您应该将输入拆分为原子令牌。这些可能是命令本身,开关-a -b -c或参数值,有时可能介于“”之间。

将输入拆分为令牌后,请验证命令是否存在。如果是,请检查令牌供应是否对命令有效。

我不知道您想要使用哪种架构。有时候人们会将一个类用于一个命令,有时会有一个类和很多方法,有时会有一个方法具有极长的情况。哪个最适合你?可能不是最后一个,但无论你选择什么都应该与命令及其工作的复杂性相匹配。

例1:

abstract class Command {
  public abstract String getName();
  public abstract int execute(String[] parameters); // not implemented in Cmd* below
}

class Cmd1 extends Command {
  public String getName()
  {
    return "Cmd1";
  }
}

class Cmd2 extends Command {
  public String getName()
  {
    return "Cmd2";
  }
}

//somewhere else:
public void execute(String[] params) {
  Command[] commands = {new Cmd1(), new Cmd2()};
  for (Command cmd: commands) {
    if (cmd.getName().equals(params[0]) {
      cmd.execute(params);
      return;
    }
  }
  throw new RuntimeException("unknown command "+params[0]);
}

示例2:

void processCmd1(String[] params);

void processCmd2(String[] params);


public static final String CMD1 = "cmd1";
public static final String CMD2 = "cmd2";
static HashSet<String> availableCommands = new HashSet<String>();
static {
  availableCommands.put(CMD1);
  availableCommands.put(CMD2);
}


{
  if (availableCommands.contains(params[0])) {
    switch(params[0]) { // java 7
      case CMD1:
        processCmd1(params[0]);
        break;
      case CMD2:
        processCmd2(params[0]);
        break;
    }
  } else {
    throw new RuntimeException("unknown command "+params[0]);
  }
}

示例3:

abstract class Command {
  public abstract String getName();
  public abstract int execute(String[] parameters); // not implemented in Cmd* below
}

class Cmd1 extends Command {
  public String getName()
  {
    return "Cmd1";
  }
}

class Cmd2 extends Command {
  public String getName()
  {
    return "Cmd2";
  }
}

static HashMap<String,Command> commandMap = new HashMap<String,Command>();
static {
  Command cmd = new Cmd1();
  commandMap.put(cmd.getName(), cmd);
  cmd = new Cmd2();
  commandMap.put(cmd.getName(), cmd);
}

//somewhere else:
public void execute(String[] params) {
  Command cmd = commandMap.get(params[0]);
  if (cmd == null) {
    throw new RuntimeException("unknown command "+params[0]);
  } else {
    cmd.execute(params);
  }
}

答案 1 :(得分:0)

有一个很好的库用于命令行参数处理。它是Apache commons CLI

答案 2 :(得分:0)

标准的设计模式是责任链或口译员,但口译员可能过度。责任链基本上是一种动态创建if / then / else决策树的方法,而不是将其硬编码为/ then / else语句。

我会预处理输入,然后使用Chain of Responsibility来解析输入。

我很确定命令行parg处理的标准库使用编译成运行代码的正式语法。至少那是我在上次使用它时的石器时代的回归(lex和yacc是受欢迎的选择),但今天它可能很特别。