Good programming practices

Control flow with String

December 27th, 2010

Motivation

Some programs are controlled by short commands in text form. They may come from user, to be read from a file, or received from another program. This make communication with such a program easier and clearer for other programs. This is a special and simplified case of Interpreter design pattern.

Applications

  • Programs, which gets parameters from the command line.
  • Servlets, for which data are sent using GET or POST.
  • Applets on web pages where the parameters are placed in HTML.

For performance reasons, it is better when there will be interpreted many groups of parameters in a single code run.

Example

Here is a simple application which, depending on the given command line parameters, performs the chosen action.

  1. import java.util.*;
  2.  
  3. public class Main {
  4. private static final Map map;
  5.  
  6. static {
  7. Map l = new HashMap(3);
  8. l.put("help", new Help());
  9. l.put("add", new Add());
  10. l.put("upper", new UpperCase());
  11. map = Collections.unmodifiableMap(l);
  12. }
  13.  
  14. private static void help() {
  15. System.out.println("Try 'java -jar interpreter.jar help' for more information");
  16. }
  17.  
  18. public static void main(String[] args) {
  19. if (args.length > 0) {
  20. Action action = map.get(args[0]);
  21. if (action != null) {
  22. String[] params = new String[args.length - 1];
  23. System.arraycopy(args, 1, params, 0, params.length);
  24. action.execute(params);
  25. } else {
  26. help();
  27. }
  28. } else {
  29. help();
  30. }
  31. }
  32. }

Main class starts at the beginning. First it creates a map of command=>action. The main method takes the parameters and the first one is used for action identifies. Other parameters are passed as an arguments to the execute method.

Class diagram

All actions implement the Action interface, making it possible to execute a method on an object taken from the map. Class Help displays help for the program, add – adds two numbers, and uppercase displays all the arguments using capital letters.

The following listing shows the program executing and output.

Terminal   
  1. Help: java -jar interpreter.jar help
  2. Usage: java -jar interpreter.jar [options]
  3. add a b Add a and b then display sum
  4. upper Display all arguments as upper letters
  5.  
  6. Add: java -jar interpreter.jar add 13 62
  7. Sum = 75
  8.  
  9. Upper case: java -jar interpreter.jar upper Hello World!
  10. HELLO
  11. WORLD!
  12.  
  13. Any other: java -jar interpreter.jar something
  14. Try 'java -jar interpreter.jar help' for more information
  15.  
  16. No arguments: java -jar interpreter.jar
  17. Try 'java -jar interpreter.jar help' for more information

Modifications

There are many opportunities to change the code above. This applies mainly to the place and method of map generating. With a large number of actions, instead of directly add objects to a map, you can create separate aarays for the commands and actions, and then add them in the loop:

  1. public static void main(String[] args) {
  2. String[] commands = new String[] { "help", "add", "upper" };
  3. Action[] actions = new Action[] { new Help(), new Add(), new UpperCase() };
  4. Map map = new HashMap(commands.length);
  5. for (int i = 0; i < commands.length; i++) {
  6. map.put(commands[i], actions[i]);
  7. }
  8. }

Summary

This pattern increases the readability of code, because we avoid many if ... else statements or switch instruction. The disadvantage is the need to create all the action's objects before any interpret, even if they aren't performed during the program.

Get all the code interpreter.jar (sources + binaries).

Leave a Response

You must be logged in to post a comment.