代码之家  ›  专栏  ›  技术社区  ›  Alfred

重构java代码

  •  6
  • Alfred  · 技术社区  · 15 年前

    好吧,我猜这个问题看起来很像:

    What is the best way to replace or substitute if..else if..else trees in programs?

    把这个问题关起来!


    String input; // input from client socket.
    if (input.equals(x)) {
      doX();
    } else if (input.equals(y)) {
      doY();
    } else {
      unknown_command();
    }
    

    它是检查套接字输入以执行某些操作的代码,但我不喜欢 if else 构造,因为每次向服务器(代码)添加新命令时,都必须添加一个新的if-else,这很难看。在删除命令时 否则 必须修改。

    5 回复  |  直到 8 年前
        1
  •  8
  •   Community CDub    8 年前

    把这些命令收集起来 Map<String, Command> 哪里 Command interface execute() 方法。

    Map<String, Command> commands = new HashMap<String, Command>();
    // Fill it with concrete Command implementations with `x`, `y` and so on as keys.
    
    // Then do:
    Command command = commands.get(input);
    if (command != null) {
        command.execute();
    } else {
        // unknown command.
    }
    

    为了进一步了解,可以考虑通过扫描实现特定接口的类来动态地填充地图( 命令 或者类路径中的特定注释。 Google Reflections 在这方面可能会有很大帮助。

    answer of Instantsoup 用我的答案。在 buildExecutor() 方法,首先从 Map 如果命令不存在于 ,然后尝试加载关联的类并将其放入 地图 . 有点懒洋洋的。这比在我的答案中扫描整个类路径并在Instantsoup的答案中每次创建它更有效。

        2
  •  3
  •   Romain    15 年前

    ICommand 这是指挥部的总合同,例如:

    public interface ICommand {
        /** @param context The command's execution context */
        public void execute(final Object context);
        public String getKeyword();
    }
    

    然后你可以使用Java的 SPI 自动发现各种实现并在 Map<String,ICommand> 然后再做 knownCommandsMap.get(input).execute(ctx)

    这实际上使您能够将服务与命令实现分离,从而有效地使这些实现可插入。

    META-INF/dummy.ICommand 在类路径中),然后将它们加载并注册为:

    final ServiceLoader<ICommand> spi = ServiceLoader.load(ICommand.class);
    for(final ICommand commandImpl : spi)
        knownCommandsMap.put(commandImpl.getKeyword(), commandImpl);
    
        3
  •  3
  •   Instantsoup    15 年前

    界面、工厂和一点思考怎么样?您仍然需要处理错误输入上的异常,但始终需要这样做。使用此方法,只需为新输入添加Executor的新实现。

    public class ExecutorFactory
    {
        public static Executor buildExecutor(String input) throws Exception
        {
            Class<Executor> forName = (Class<Executor>) Class.forName(input);
            return (Executor) executorClass.newInstance();
        }
    }
    
    public interface Executor
    {
        public void execute();
    }
    
    
    public class InputA implements Executor
    {
        public void execute()
        {
            // do A stuff
        }
    }
    
    public class InputB implements Executor
    {
        public void execute()
        {
            // do B stuff
        }
    }
    

    您的代码示例将变成

    String input;
    ExecutorFactory.buildExecutor(input).execute();
    
        4
  •  2
  •   Itay Maman    15 年前

    在枚举类上构建命令模式可以减少一些样板代码。假设x在 input.equals(x) “XX”和y在吗 input.equals(y) 是“YY”

    enum Commands {
       XX {
         public void execute() { doX(); }        
       },
       YY {
         public void execute() { doY(); }        
       };
    
       public abstract void execute();
    }
    
    String input = ...; // Get it from somewhere
    
    try {
      Commands.valueOf(input).execute();
    }
    catch(IllegalArgumentException e) {
       unknown_command();
    }
    
        5
  •  1
  •   Anon    15 年前

    你说你在处理来自套接字的输入。投入多少?有多复杂?结构如何?

    根据这些问题的答案,你最好写一个语法,让解析器生成器(例如, ANTLR )生成输入处理代码。