The Command Pattern TutorialFrom WikiJavabuy this book
This tutorial explains a complete example of a Command Pattern. The Command pattern is very useful in many occasions, for example when you don't know a priori the whole set of actions that you will want to perform. In this situation you will use the command pattern which granting you an extreme flexibility. The client doesn't need to know which actions are available and no details about them.
the articleOverviewThe program I'm going to build to show you the Command Pattern has the following package structure: the base package is: com.wikijava.patterns.commandNoResourceBundles +- commandNoResourceBundles +- actions - Day.java - IAction.java - Night.java - ActionCommander.java - ActionClient.java - CommandResourceBundleManager.java - commands.properties - ActionCommanderException.java The core class of the tutorial is the 'ActionCommander.java' class, which is responsible of chosing which action to execute. The 'IAction.java' interface is also important as all the actions must implement it. The action classes ('Day.java' and 'Night.java') implement the 'IAction' interface. The 'ActionClient.java' contains the main method. In the next paragraphs I'll explain better what's going on in the 'ActionCommander' class and in the actions. The 'ActionCommander' classThe action commander class is the core of the command pattern. It is responsible of the choice of which command to execute. The class takes also care of executing the actions and to return their result. All is left for the client is to instantiate the 'ActionCommander' class and start executing commands on it. Note that the command names have been externalized to a resource bundle. This is an important step that allows you to manage the command strings (crucial to identifying the commands) package com.wikijava.patterns.commandNoResourceBundles; import com.wikijava.patterns.command.actions.Day; import com.wikijava.patterns.command.actions.IAction; import com.wikijava.patterns.command.actions.Night; /** * Implementing the command pattern, checks against the command.properties * resource bundle for what action has been called and executes it. * * @author Giulio */ public class ActionCommander { public String call(String command, String name) throws ActionCommanderException { /* * finds which command is to execute. it's now only * checking the requested command, but it may also use * more complex rules. */ if (command.equalsIgnoreCase(CommandResourceBundleManager .getString("ActionCommander.command.day"))) { //$NON-NLS-1$ // creates the action object IAction day = new Day(); // executes the action and returns the result. return day.execute(name); } else if (command.equalsIgnoreCase(CommandResourceBundleManager .getString("ActionCommander.command.night"))) { //$NON-NLS-1$ IAction night = new Night(); return night.execute(name); } else { throw new ActionCommanderException("command not Found"); //$NON-NLS-1$ } } } the ActionClient.classThe 'ActionClient' class is the entry point of this example. It takes the input from the command line and passes it to the 'ActionCommander.call' method. In this class you can really understand the infinite power of this pattern, all the client has to do is to use the 'ActionCommander.call' method, to execute commands, the client doesn't even have to know which commands are available, as they are passed using variables. package com.wikijava.patterns.commandNoResourceBundles; /** * shows the usage of the ActionCommander for executing commands * * @author Giulio */ public class ActionClient { private static final String USAGE = "usage: \nActionClient [day|night] <name>"; /** * Instantiates an ActionCommander Object and executes commands in it * * @param args * one single command, the name of the command to execute */ public static void main(String[] args) { if (args.length != 2) { System.err.println(USAGE); return; } final String command = args[0]; final String name = args[1]; // instantiates the actionCommander, ActionCommander actionCommander = new ActionCommander(); try { // calls the action. String result = actionCommander.call(command, name); // prints the result System.out.println("the result was: " + result); //$NON-NLS-1$ } catch (ActionCommanderException e) { // something may go wrong. In normal situation you would put here a // proper error handler System.err.println(USAGE); } } } The 'IAction' interfaceThe only method needed in this simple example is the 'execute()'. It's important to have an interface common to all the actions, for better standardization. This greatly simplifies the complexity of the 'ActionCommander' class. package com.wikijava.patterns.command.actions; /** * interface for Actions to be executed by the ActionCommander * * @author Giulio */ public interface IAction { /** * * executes the action * * @param name * @return a String with the information about which command has been * executed */ public String execute(String name); } the actionsThe action Day package com.wikijava.patterns.commandNoResourceBundles.actions; /** * Day action to be executed by the ActionCommander * * @author Giulio */ public class Day implements IAction { public String execute(String name) { return "from the day command: hello " + name; //$NON-NLS-1$ } } The night Action package com.wikijava.patterns.commandNoResourceBundles.actions; /** * night action to be executed by the ActionCommander * * @author Giulio */ public class Night implements IAction { public String execute(String name) { return "from the night command: hello " + name; //$NON-NLS-1$ } } the Resource BundleThis was automagically generated by Eclipse the 'CommandResourceBundleManager' class: package com.wikijava.patterns.commandNoResourceBundles; import java.util.MissingResourceException; import java.util.ResourceBundle; public class CommandResourceBundleManager { private static final String BUNDLE_NAME = "com.wikijava.patterns.commandNoResourceBundles.commands"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private CommandResourceBundleManager() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } the 'commands.properties' file: ActionCommander.command.day=day ActionCommander.command.night=night the 'ActionCommanderException' ExceptionThe exception is also very straightforward, I had it automatically generated by Eclipse and I didn't touch it any further: package com.wikijava.patterns.commandNoResourceBundles; public class ActionCommanderException extends Exception { public ActionCommanderException() { // TODO Auto-generated constructor stub } public ActionCommanderException(String message) { super(message); // TODO Auto-generated constructor stub } public ActionCommanderException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } public ActionCommanderException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } } |
