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

编写此Java代码的更好方法?[关闭]

  •  1
  • Macha  · 技术社区  · 17 年前
    public void handleParsedCommand(String[] commandArr) {
        if(commandArr[0].equalsIgnoreCase("message")) {
            int target = Integer.parseInt(commandArr[1]);
            String message = commandArr[2];
            MachatServer.sendMessage(target, this.conId, message);
        } else if(commandArr[0].equalsIgnoreCase("quit")) {
            // Tell the server to disconnect us.
            MachatServer.disconnect(conId);
        } else if(commandArr[0].equalsIgnoreCase("confirmconnect")) {
           // Blah blah and so on for another 10 types of command
        } else {
            try {
                out.write("Unknown: " + commandArr[0] + "\n");
            } catch (IOException e) {
                System.out.println("Failed output warning of unknown command.");
            }
        }
    }
    

    我有这部分服务器代码来处理消息类型。每条消息都包含以下类型 commandArr[0] commandArr[] String 值不能在中使用 switch 开关

    8 回复  |  直到 16 年前
        1
  •  8
  •   Bob    17 年前

    Command Design Pattern .

    /*the Command interface*/
    public interface ICommand {
        void execute(String[] commandArr);
    }
    
    public class Message implements ICommand {
        void execute(String[] commandArr) {
            int target = Integer.parseInt(commandArr[1]);
            String message = commandArr[2];
            MachatServer.sendMessage(target, this.conId, message);
        }
    }
    
    //same type of class for other commands
    
    public class CommandManager {
        public ICommand getCommand(String commandName) {
            //store all the commands in a hashtable. 
            //Pull them out by name as requested.
        }
    
        //Esko's suggestion from comments
        public static void executeImmediately(String[] commandArr) {
            getCommand(commandArr[0]).execute(commandArr);
        }
    }
    
    
    public void handleParsedCommand(String[] commandArr) {
    
        ICommand command = CommandManager.getCommand(commandArr[0]);
        command.execute(commandArr);
    
    //or Esko
    
        CommandManager.executeImmediately(commandArr);
    
    }
    
        2
  •  6
  •   dmeister    17 年前

    以下是两种使用枚举的变体,它们(几乎)以更易读的方式提供相同的行为:

    enum CommandType {
    MESSAGE,
    QUIT,
    CONFIRMCONNECT
    }
    
    public void handleParsedCommand(String[] commandArr) {
        CommandType cmd = null;
    
        try {
            cmd = CommandType.valueOf(commandArr[0].toUpperCase());
        } catch (IllegalArgumentException e) {
            // this kind of error handling, seems a bit strange, by the way.
            try {
                out.write("Unknown: " + commandArr[0] + "\n");
            } catch (IOException e) {
               System.out.println("Failed output warning of unknown command.");
            }
            return;
        }
        switch(cmd) {
            case MESSAGE:
                int target = Integer.parseInt(commandArr[1]);
                String message = commandArr[2];
                MachatServer.sendMessage(target, this.conId, message);
            case QUIT:
                // Tell the server to disconnect us.
                MachatServer.disconnect(conId);
            case CONFIRMCONNECT:
                // Blah blah and so on for another 10 types of command
            }
        }
    }
    

    主要的好处是代码更具可读性,但你避免为每种情况创建新的方法或类,如果处理代码只有一两行,这是不允许的。

    enum CommandType {
        MESSAGE {
            void execute(CommandProcessor cp, String[] params) {
                int target = Integer.parseInt(params[1]);
                String message = params[2];
                MachatServer.sendMessage(target, cp.conId, message);        
            }
        },
        QUIT {
            void execute(CommandProcessor cp, params param) {
                MachatServer.disconnect(cp.conId);  
            }
        },
        CONFIRMCONNECT {
            void execute(CommandProcessor cp, params param) {
                  // Blah blah and so on for another 10 types of command
            }
        };
    
        abstract void execute(CommandProcessor cp, String[] param);
    }
    public void handleParsedCommand(String[] commandArr) {
        CommandType cmd = null;
    
        try {
            cmd = CommandType.valueOf(commandArr[0].toUpperCase());
        } catch (IllegalArgumentException e) {
            try {
                out.write("Unknown: " + commandArr[0] + "\n");
            } catch (IOException e) {
                System.out.println("Failed output warning of unknown command.");
            }
            return;
        }
        cmd.execute(this, commandArr);
    }
    
        3
  •  2
  •   OscarRyz    17 年前

    是的,看起来像 Command Prototype 图案给我。

    在命令中,您定义要执行的操作,原型是将每个命令的实例放置在查找表中,并“克隆”它们以每次执行。

    重构过程如下:

    之前:

    public void handleParsedCommand(String[] commandArr) {
            if(commandArr[0].equalsIgnoreCase("message")) {
            int target = Integer.parseInt(commandArr[1]);
            String message = commandArr[2];
            MachatServer.sendMessage(target, this.conId, message);
        } else if(commandArr[0].equalsIgnoreCase("quit")) {
            // Tell the server to disconnect us.
            MachatServer.disconnect(conId);
        } else if(commandArr[0].equalsIgnoreCase("confirmconnect")) {
           // Blah blah and so on for another 10 types of command
        } else {
            try {
                out.write("Unknown: " + commandArr[0] + "\n");
            } catch (IOException e) {
                System.out.println("Failed output warning of unknown command.");
            }
        }
    }
    

    之后:

    public void handleParsedCommand(String[] commandArr) {
        Command.getCommand( commandArr ).execute();
    }
    
    
    // Define the command and a lookup table
    abstract  class Command {
    
        // Factory using prototype 
        public static Command getCommand( String [] commandArr ) {
            // find the handling command 
            Command commandPrototype = commandMap.get( commandArr[0] );
            // if none was found, then use "uknown"
            if ( commandPrototype == null ) {
                 commandPrototype = commandMap.get("unknown");
            }
            // Create an instance using clone
            Command instance = commandPrototype.clone();
            instance.args = commanrArr;
            return instance;
    
        }
    
        // lookup table ( switch substitute )
        private static Map<String,Command> commandsMap = new HashMap()<String,Command>(){{
              put("message"       , new MessagCommand());
              put("quit"          , new QuitCommand());
              put("confirmconnect", new ConfirmConnectCommand());
              ...
              put("unknow"        , new UnknownCommand());
    
        }};
    
    
        // args of the command
        private String [] args;
    
    
        public void execute();
    
        String [] getArgs(){
            return this.args;
        }
    
    
    }
    

    并提供具体实现

    class MessageCommand extends Command {
         public void execute(){
            int target = Integer.parseInt(commandArr[1]);
            String message = commandArr[2];
            MachatServer.sendMessage(target, this.conId, message);
         }
    }
    
    class MessageCommand extends Command {
         public void execute(){
            int target = Integer.parseInt(getArgs()[1]);
            String message = getArgs()[2];
            MachatServer.sendMessage(target, this.conId, message);
         }
    }
    
    class QuitCommand extends Command {
         public void execute() {
          MachatServer.disconnect(conId);
         }
     }
    
     class ConfirmConnectCommand extends Command {
         public void execute() {
         /// blah blah blah 
         }
     }
     class UnknowCommand extends Command  {
         public void execute() {
             try {
                out.write("Unknown: " + commandArr[0] + "\n");
             } catch (IOException e) {
                System.out.println("Failed output warning of unknown command.");
             }
         }
     }
    
     // ... other 10 implementations here... 
    
        4
  •  1
  •   ChssPly76    17 年前

    看一看 Commons CLI 它是一个命令行参数解析器。

    这里是 some examples 它的使用。

        5
  •  1
  •   z -    17 年前

    您可以使用 enums

        6
  •  1
  •   Yishai    17 年前

        7
  •  0
  •   Tom Hawtin - tackline    17 年前

    equalsIgnoreCase 有点长,所以先将案例规范化(不要选择默认语言环境!)。

    可以使用 enum s破解a switch 的 Swting s.JDK7可以包括 String ,IIRC。

        8
  •  0
  •   Chris Thompson    17 年前

    commandArr[0] .

    所以你的xml看起来像

    <property name="commands">
      <map>
        <entry>
            <key>
               <value>message</value>
            </key>
            <ref bean="messageCommand" />
         </entry>
      </map>
     </property>
     <bean id="messageCommand" ref="org.yourorg.yourproject.MessageCommand" />
    

    然后在你的代码中。..

    commands.get(commandArr[0]).execute() //or whatever
    

    这允许您不运行任何类型的初始化代码。您所要做的就是膨胀xml。Spring为您填充地图。此外,您可以使用类似的语法在类中定义任何必要的数据成员。此外,如果你需要添加功能,你所要做的就是更改xml,而不是处理和重新编译代码。我个人是huuuge的粉丝:)

    this article 了解IoC的简要概述,然后查看 this article for the documentation