0

So, I'll describe my problem. User enters a command. I need to process that command and run a specific function accordingly.

I used a switch statement for finding what command was entered by user, but I think that it was getting rather messy. Should I keep going with this approach?

I decided to create a class for every possible command, put them into an array and, instead of switch statement, use a loop to check if any of the commands fits and call the function stored in that command object. At the moment I have about 10 commands implemented, but the number will grow.

Creating a new file for every new command class looks really bothersome and possibly messy, so I wonder if there is a better way to achieve what I want or perhaps there is a better way to implement everything?

zubergu
  • 3,646
  • 3
  • 25
  • 38
user1242967
  • 1,220
  • 3
  • 18
  • 30
  • Perhaps you want one Command class with a field of type `String` that represents the command. Maybe the class has methods that enable it to write to a file. – BitNinja May 06 '14 at 22:11
  • Your question and title seem unrelated, maybe think of a different title that better reflects the question? – Tim May 06 '14 at 22:12
  • 1
    I think the question is fine and so is the title. No need for code. – apxcode May 06 '14 at 22:13
  • A hashmap can pair a key to an object (like a string to an object that runs the command). I find that quite pleasant for this sort of thing – Richard Tingle May 06 '14 at 22:14
  • @FunctionR agreed. I don't think it deserved a downvote, to clarify. Also, including code helps visualize problems, so I am always for that although it isn't strictly necessary. – Carrie Kendall May 06 '14 at 22:15
  • 1
    Another approach would be to create a Command class and have a public inner class for each command/function. This way you don't need to create separate .java files for each command, and you individually make use of each command via Command.FirstCommand etc. – josephus May 06 '14 at 22:16
  • @JosephusVillarey That would solve a problem with having a lot of .java files, but how I would I know which function to call? I would need another switch statement? Or am I missing something obvious? I don't know if comments section is the right place to add more details, if not, I will edit the question. Almost all commands have several possible names associated with them. I will store possible aliases in the Command class. The Command class will also have a method which returns true if passed string is one of the aliases. But my main question concerns the large number of .java files. – user1242967 May 06 '14 at 22:24
  • would you mind sharing what kind of commands you are passing as a user? are you getting input from the keyboard? – josephus May 06 '14 at 22:31
  • Sure, I am writing a Logo clone. So user can pass commands such as: forward 100 fd 50 right 90 – user1242967 May 06 '14 at 22:34
  • so it's from the keyboard, i suppose? – josephus May 06 '14 at 22:35
  • Yes it is, I forgot to mention it. – user1242967 May 06 '14 at 22:36
  • Please see my proposed solution as an answer below. – josephus May 06 '14 at 22:52

3 Answers3

0

I like your approach of having a class to represent each command, it is actually very smart. Perhaps you didn't know this but you are touching on key aspects of the State Pattern, which is what I would use for this kind of problem.

So you could leave your code the way you have it or implement a more complex but more flexible version of your code using the State Pattern.

apxcode
  • 7,696
  • 7
  • 30
  • 41
  • I don't see how this has anything to do with the state pattern. It's just do X or Y depending on what the user inputs – Tim May 06 '14 at 22:13
  • What is the main purpose of the State Pattern? Also wait until someone recommend an `enum` and it will be more obvious. The way I see OPs question is: User enters command, user goes into a section of code, hence a state. – apxcode May 06 '14 at 22:15
  • Executing some code is not the same as being in a state. If it were so, every program ever made would implement the state pattern – Tim May 06 '14 at 22:19
  • I didn't say "executing some code" I said goes into a section of code. On that note, a lot of programs benefit from FSM. Also did you see the other answer about `enums` that was some freaky prediction. – apxcode May 06 '14 at 22:23
0

I think you could also use an enum to represent the various commands, where the enum implements an interface, and therefore each enum instance has to implement the "command" method, whatever you want to call it (doIt(), run(), etc).

Like this: Why would an Enum implement an Interface?

Community
  • 1
  • 1
Jake Toronto
  • 3,524
  • 2
  • 23
  • 27
  • Each command should know its own name (multiple names). I don't really have much experience with enums in Java, so I have to ask, is it possible to implement this enum in such way that every instance of this enum would store a list of names, had a method to that checks if string matches one of the names and a method to run a command? Sorry to bother you with this basic stuff. – user1242967 May 06 '14 at 22:51
  • You might try following this pattern: http://binkley.blogspot.com/2006/02/using-java-5-enums-for-command-pattern.html The basic idea is if you name your enums the same as the commands that are being entered, then you can say `CommandEnum.valueOf(command).run()`. – Jake Toronto May 07 '14 at 18:27
-1

Another approach would be to create a Command class and have a public inner class for each command/function. This way you don't need to create separate .java files for each command, and you individually make use of each command via Command.FirstCommand etc.

As for trying to not use a switch-case to determine what command you need to call, take a look at my example code below:

public class Command {
    class InnerCommand implements InnerInterface {
        // implement execute command
    }

    class AnotherInnerCOmmand implements InnerInterface {
        // implement execute command
    }

    interface InnerInterface {
        void executeCommand();
    }
}

You can use a HashMap<String, InnerInterface> to map String commands to a specific command that you want to run based on the input, make sure to populate the HashMap somewhere else (maybe in your Command class). Then instead of using a switch-case you only need to do:

public static void doCommand(String commandString) {
    HashMap<String, InnerInterface> commandsMap = new HashMap<String, Command.InnerInterface>();
    InnerInterface commandInterface = commandsMap.get(commandString);
}

Then it's just a matter of calling commandInterface.executeCommand();

josephus
  • 8,284
  • 1
  • 37
  • 57