views:

184

answers:

5

I want to write an apps that accepts user command. The user command is used in this format:

command -parameter

For example, the app can have "Copy", "Paste", "Delete" command I am thinking the program should work like this :

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
     **/


}

So, it works, but I think it will become more and more complex when I have more command in my program, also, it is different to read. Any ideas to simply the logic?

+3  A: 

Use a library to keep the messiness of command line argument parsing out of your code, for example args4j.

Thilo
+7  A: 

Depending on how simple your command line syntax is, a simple enum may be your solution

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();
    }
}

Compile and run this with java Command paste, java Command bleh, etc. You'll want to pass the rest of args to the enum in your production code. Also, valueOf throws IllegalArgumentException if no enum constant is found with the specified name.


If your syntax grows to be more complex, though, you may want to use libraries specifically designed for command line parsing, e.g. Apache Commons CLI.

polygenelubricants
This isn't really that much better than a pile of if/elseifs. If you're using enums it'd be much nicer to move the logic into a method of the enum, then you can simply use Command.valueOf(...).execute() instead of all the messy checking or switching.
Chris Smith
Thanks for suggestion! Added!
polygenelubricants
This is pretty nice now in terms of code quantity, even if a bit magic.
spong
A: 

There are many libraries that can handle this situation instead of writing all the code down.

LucaB
+6  A: 

If you are concerned about handling the command line parameters then Commons CLI is meant for this.
Go through the CommandLineParser

and if you are concerned about the complexity of your if-else then you can use Command Pattern

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 
 }

-- then

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();

}
}
Rakesh Juyal
+1 this is the answer. I'd also be very tempted to use reflection to create the Command class from the String passed in to get rid of the requirement to build the commandMap which could become onerous and somewhat messy as the number of commands increases.
Robin
+1 Yes, this would be my suggestion as well if you want to get rid of your `if` clauses and make it a bit more flexible.
Martin Wickman
+1  A: 

When I see lots of if/then/else code, I immediately think of polymorphism as a possible solution.

A Command interface and a Map would be a fine way to solve this problem. If I were writing this in Java, it might look like this:

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

If your operations are multi-threaded, you can simply reuse the Runnable interface for Commands that don't return a value and Callable<T> for ones that do.

In either case, now your if/then/else construct is a Map where the key is the name and the value is the Command object. You look up a Command by providing the name key. You add a new command by writing a new implementation of the Command interface and adding it to the Map. Initializing the Map is something you do on startup. You can even externalize it as configuration so you don't have to modify code to add new ones (Open/Closed Principle).

duffymo