Wednesday, 23rd June 2010
The new frontier for learning Java

The Command Pattern Tutorial

From WikiJava

Jump to: navigation, search
The author suggests:

buy 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.


Image:250px-Subversion.png
You can download the complete code of this article from the Subversion repository at this link

Using the username:readonly and password: readonly

See the using the SVN repository instructions page for more help about this.

Contents

the article

Overview

The 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' class

The 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.class

The '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' interface

The 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 actions

The 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 Bundle

This 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' Exception

The 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
    }
 
}

Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page


Title (required):

Website:

Comment: