【问题标题】:How to simplify this logic/code?如何简化这个逻辑/代码?
【发布时间】:2011-01-29 18:30:51
【问题描述】:

我想编写一个接受用户命令的应用程序。用户命令以这种格式使用:

命令-参数

例如,应用程序可以有“复制”、“粘贴”、“删除”命令 我认为程序应该像这样工作:

public static void main(String args[]){

   if(args[0].equalsIgnoreCase("COPY")){
     //handle the copy command

   } else if(args[0].equalsIgnoreCase("PASTE")){
     //handle the copy command


   }/**
    code skipped
     **/


}

所以,它可以工作,但我认为当我的程序中有更多命令时它会变得越来越复杂,而且阅读起来也会有所不同。有什么简单的逻辑思路吗?

【问题讨论】:

标签: java optimization


【解决方案1】:

如果您担心处理命令行参数,那么Commons CLI 就是为此而生的。
通过CommandLineParser

如果您担心 if-else 的复杂性,那么您可以使用命令模式

public interface Command {
     void exec();
}

public class Copy implements Command {    
     void exec() {
          // your copy Code 
     }
}

public class Paste implements Command {    
     void exec() {
          // your Paste Code 
     }
}


public class Delete implements Command {    
     void exec() {
          // your Delete Code 
 }

-- 那么

public static void main(String args[]){
Map commandMap<String,Command> = new HashMap<String,Command>();
commandMap.put("Copy", new Copy());
commandMap.put("Paste", new Paste());
commandMap.put("Delete", new Delete());

if ( commandMap.containsKey(args[0]) ){
commandMap.get(args[0]).exec();

}
}

【讨论】:

  • +1 这就是答案。我也很想使用反射从传入的字符串创建 Command 类,以摆脱构建 commandMap 的要求,随着命令数量的增加,这可能会变得繁重且有些混乱。
  • +1 是的,如果您想摆脱 if 子句并使其更加灵活,这也是我的建议。
【解决方案2】:

根据您的命令行语法的简单程度,一个简单的enum 可能是您的解决方案

public enum Command {
    COPY {
        @Override void execute() {
            System.out.println("Copying...");
        }
    },
    PASTE {
        @Override void execute() {
            System.out.println("Pasting...");
        }       
    },
    DELETE  {
        @Override void execute() {
            System.out.println("Deleting...");          
        }
    },
    ;

    abstract void execute();

    public static void main(String args[]) {
        Command c = Command.valueOf(args[0].toUpperCase());
        c.execute();
    }
}

使用java Command pastejava Command bleh 等编译并运行它。您需要将args 的其余部分传递给生产代码中的枚举。此外,如果没有找到具有指定名称的枚举常量,valueOf 将抛出 IllegalArgumentException


但是,如果您的语法变得更加复杂,您可能希望使用专为命令行解析而设计的库,例如Apache Commons CLI.

【讨论】:

  • 这并不比一堆 if/elseifs 好多少。如果您使用枚举,将逻辑移动到枚举的方法中会更好,那么您可以简单地使用 Command.valueOf(...).execute() 而不是所有凌乱的检查或切换。
  • 这在代码数量方面已经相当不错了,即使有点神奇。
【解决方案3】:

使用库来避免代码中命令行参数解析的混乱,例如args4j

【讨论】:

    【解决方案4】:

    当我看到大量 if/then/else 代码时,我立即想到多态性是一种可能的解决方案。

    命令接口和地图将是解决此问题的好方法。如果我用 Java 编写它,它可能看起来像这样:

    public interface Command<T, V>
    {
        V execute(T parameter) throws Exception;
    }
    

    如果您的操作是多线程的,您可以简单地将 Runnable 接口用于不返回值的命令,而将 Callable 用于返回值的命令。

    在任何一种情况下,现在您的 if/then/else 构造都是一个 Map,其中键是名称,值是 Command 对象。您通过提供名称键来查找命令。您可以通过编写 Command 接口的新实现并将其添加到 Map 来添加新命令。初始化地图是您在启动时执行的操作。您甚至可以将其外部化为配置,这样您就不必修改代码来添加新代码(开放/封闭原则)。

    【讨论】:

      【解决方案5】:

      有很多库可以处理这种情况,而不是把所有的代码都写下来。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-21
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 2011-01-26
        • 2021-01-09
        • 2012-03-08
        • 1970-01-01
        相关资源
        最近更新 更多