Your Guide to Design Patterns – Command Pattern

Design Patterns - Command Pattern

This week we’ll continue our exploration of design patterns and look at a very commonly used behavioural pattern, the Command pattern.

The Gang of Four book defines the Command pattern as follows:

“Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.”

Understanding the Command Pattern

Objects communicate when one object (the invoker) sends a request to another object (the receiver). The receiver processes the request in some way, and sends a response back to the invoker. The invoker and the receiver must be tightly coupled for this to happen. Ideally objects should be loosely coupled, so that changes to one component do not affect any of the other components.

The Command Pattern is a proven solution to the problem of tightly coupled invokers and receivers. Requests are encapsulated as objects that are passed around just like any other object. These request objects are called commands.

The invoker issues commands without knowing anything about the receiver. In fact, the invoker doesn’t even know what method will be called by the command. There is loose coupling between the invoker and receiver, with the command object acting as a go-between.

The command object has an execute() method, and optionally an undo() method. The code within the execute() method invokes a method of the receiver, while the undo() undoes the effects of the previous method. The command object is created by the client and passed to the invoker. The invoker issues the command when needed. The invoker doesn’t know what the actual implementations of the execute() and undo() methods are, and even which receiver is involved.

Command Pattern: The Problem Statement

In the previous post on the Bridge Pattern, we had created mechanised fighting units, like self-driving armoured vehicles and autonomous fighting robots. We modelled these robots and vehicles as MechanisedFightingVehicle and MechanisedFightingRobots. These implemented the FightingUnit interface. We implemented remote controls to command the units to advance, retreat and fight.

There was tight coupling between the RemoteControl class and the FightingUnit interface. A RemoteControl contained a FightingUnit object, and specific FightingUnit methods were called by the RemoteControl methods. There was nothing wrong with the design. It was appropriate for what we wanted to do, which was to control a FightingUnit with a RemoteControl.

However, if we wanted to control a number of other classes with different interfaces, this design wouldn’t work. We would want a design that promoted much looser coupling between the invoker and the receiver.

Command Pattern: Example Code

This is where the Command Pattern comes in.

We can create command classes that represent the operations that can be invoked on a receiver. We hide the receiver and method details within each concrete command class. The invoker can issue these commands without knowing anything about the receiver or the exact methods called.

Let’s start with a Command interface:

public interface Command {
  public void execute();
  public void undo;
}

Our receivers are currently FightingUnits, but in the future could be anything we wanted to control: non-fighting units like medics, supply vehicles, ambulances, whatever. We don’t need to use our current RemoteControls. We can change the way we control units. We could let an AI engine at HeadQuarters control the units directly. We could even send messages to them directly using the Observer pattern behind the scenes. We could use the Command pattern in any other game or application. The possibilities are endless.

Two of our concrete Command classes follow:

public class UnitAdvanceCommand implements Command {

   private FightingUnit unit;

   public UnitAdvanceCommand(FightingUnit unit){
     this.unit = unit;
   }
   @Override
   public void execute(){
     System.out.println(
      "UnitAdvanceCommand.execute(): invoking advance()");
     unit.advance();
   }
   @Override
   public void undo(){
     System.out.println(
      "UnitAdvanceCommand.undo(): Undoing previous action by invoking retreat()");
      unit.retreat();
   }
}

public class UnitTurnCommand implements Command {

   private FightingUnit unit;
   private int degrees;

   public UnitTurnCommand(FightingUnit unit, int degrees){
      this.unit = unit;
      this.degrees = degrees;
   }
   @Override
   public void execute(int degrees){
      System.out.println("UnitTurnCommand.execute(): turning " + degrees + " degrees.");
      unit.turn(degrees);
   }
   @Override
   public void undo(){
      System.out.println("UnitTurnCommand.undo(): turning back " + degrees + " degrees.");
      unit.turn(-degrees);
   }
}

This version of the RemoteControl interface includes an undo() method. This could possibly be implemented as a button on the remote control:

public interface RemoteControl {
   public void engage();
   public void turn(int degrees);
   public void forward();
   public void back();
   public void undo();
}

The Command pattern version of the AbstractRemoteControl doesn’t contain an FightingUnit object. Rather, the client code supplies the remote control with a number of command objects, each of which contains a FightingUnit.

public class AbstractRemoteControl implements RemoteControl {

   private Command forwardCommand;
   private Command backCommand;
   private Command turnCommand;
   private Command engageCommand;
   private Command previousCommand;

   // Setters for the supported commands 

   public void setForwardCommand(Command forwardCommand) {
      this.forwardCommand = forwardCommand;
   }
   public void setTurnCommand(Command turnCommand) {
      this.turnCommand = turnCommand;
   }
   public void setBackCommand(Command backCommand) {
      this.backCommand = backCommand;
   }
   public void setEngageCommand(Command engageCommand) {
      this.engageCommand = engageCommand;
   }

   // Remote controls - forward, back, turn, engage 

   @Override
   public void forward() {
      execute(forwardCommand);
   }
   @Override
   public void back() {
      execute(backCommand);
   }
   @Override
   public void engage() {
      execute(engageCommand);
   }
   @Override
   public void turn() {
      execute(turnCommand);
   }

   // Undo button 

   @Override
   public void undo() {
      if (previousCommand == null) return;
      previousCommand.undo();
   }

   // Common implementation for all controls

   private void execute(Command command) {
      if (command == null) return;
      command.execute();
      previousCommand = command;
   }

   @Override
   public String toString() {
      return getClass().getName();
   }
} // end of class

We could have defined a constructor for the AbstractRemoteControl instead of a separate setter for each command. Having four parameters for a constructor is still workable. A maximum of three to four parameters for any method is a good programming rule of thumb.

Currently the AbstractRemoteControl class only supports one level of undo functionality with the previousCommand field. We could build in unlimited undo operations by creating a stack of all previously executed commands, and progressively pop previous commands off the stack.

The client code creates the various RemoteControls and passes the commands to them. A snippet of the client code follows:

// In client code
FightingUnit unit = new MechanisedFightingRobot(); // or MechanisedFightingVehicle
AbstractRemoteControl remote = new BasicRemoteControl();
System.out.println(remote);

remote.setForwardCommand(new UnitAdvanceCommand(unit) );
remote.setBackCommand   (new UnitRetreatCommand(unit) );
remote.setTurnCommand   (new UnitTurnCommand(unit, 10) );
remote.setEngageCommand (new UnitFightCommand(unit) );

System.out.println("Moving forward...");
remote.forward();

System.out.println("Moving back...");
remote.back();

System.out.println("Turning...");
remote.turn();

System.out.println("Undoing previous command");
remote.undo();

System.out.println("Engaging...");
remote.engage();

System.out.println("Undoing previous command");
remote.undo();
// more code... 

Pros and Cons of the Command Pattern

Using the Command pattern has a lot of benefits:

  • We can create new RemoteControl classes without changing any of the existing FightingUnit classes and vice versa.
  • We can easily add any other controller types and receiver types.
  • We can easily add different parameterised commands.

However, the Command pattern does make the code more complex and more difficult to understand. It may be overkill for a simple application.

What’s next?

In the weeks ahead, we’ll continue examining some of the more useful design patterns. Stay tuned!

As always, please share your comments and questions.

This week we’ll continue our exploration of design patterns and look at another behavioural pattern, the Interpreter pattern.

The Gang of Four book defines the Interpreter pattern as:

“Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.”

The Interpreter pattern allows us to implement a simple language to use inside an application. We define a class to represent each rule of the language (its grammar). We also implement an interpreter that operates on instances of these classes. This interpreter parses and executes the sentences of the language.

The pattern works well when we have a simple language/grammar to implement. As the grammar gets more complex, it becomes harder to maintain. With a large number of language rules, tools like parser generators are better options. These tools can interpret expressions without building abstract syntax trees. This is more efficient and can save memory space.

We very rarely use the Interpreter pattern, because as developers we hardly ever create our own languages. To use it properly, we need to know a lot about formal grammars. Formal grammars are used to create languages.

Examples

A well-known example of an interpreter is JavaScript code that runs in a web page on a browser. JavaScript is an programming language, and as such, has a grammar representation. A JavaScript interpreter uses that grammar representation to interpret and run JavaScript code. A JavaScript interpreter is built into every major browser.

SQL is another good example. An SQL interpreter is built into all relational database management systems.

In Java SE, the Interpreter pattern is used in the java.util.Pattern and java.text.Normalizer classes and all subclasses of java.text.Format.

Other examples of the Interpreter pattern are the Unified Expression Language (javax.el API) used in JSP and JSF, and the Spring Expression Language (SpEL).

Expression Hierarchy

We use the Interpreter pattern to define a class-based representation for the grammar of our language.

We create an AbstractExpression interface (or abstract class) as the root of our class hierarchy. This is used to interpret a context. The interface defines an abstract interpret() method that takes the context as a parameter. The context is an input stream (generally a string) containing the language sentences that must be parsed.

We then create concrete classes implementing the AbstractExpression interface. Each class represents an expression in our language. Each expression can be either a terminal or non-terminal expression:

  • Terminal expressions are the basic elements of our language. We define these with a formal grammar.
  • Non-terminal expressions (also called syntactic variables) are replaced by groups of terminal symbols based on the grammar rules. The non-terminal classes are generally implemented using a composite design pattern, while the terminal expressions are leaf objects.

A non-terminal expression may have one or more AbstractExpressions associated in it. This means it can be recursively interpreted. The interpretation process ends with a terminal expression that returns the result.

Representing each grammar rule as a class makes the language easy to implement, change or extend. We can even add extra methods to the classes (other than the interpret() method) to support extra functionality like validation and pretty printing.

The Interpreter

We also need to create an interpreter that deals with this grammar. All of the expressions need to be processed, and from them we build an Abstract Syntax Tree (AST). The AST is just a sentence defined using the syntax of our language. This sentence is the context. The interpreter then parses the AST and produces the required output.

To interpret the language, we call the interpret() method on each expression type. The interpret() method is passed the context. It then matches and evaluates the expressions, and returns a result. Each expression will affect the context, change its state, and either continue the interpretation or return the result. The context is reused by all expressions during the interpretation process.

Interpreter Pattern: Design Example

Going back to our first person shooter game, we’ve already created mechanised fighting units. We’ve also developed remote controls that allow us to command them to fight and move towards specific targets. (See the post on the Command pattern).

We now decide that it will be a great new feature for players to be able to type in a string of commands that the fighting units could interpret and run. A player could even strategise an entire troop deployment and attack plan, and save this as a small text file that could be run by the command interpreter.

We will have to define a grammar for this language. At first we’ll make it fairly small, with the possibility of expanding it later. What sort of commands would we like to run? Our first thoughts may lead us to a set of commands like:

with unit #number
   move x, y
   attack if enemy found
   retreat if health < 20%
end with

Implementation

The code implementation of this language is somewhat long for one post, so we’ll leave this post on a cliff-hanger, and continue it in next week’s post.

Stay tuned, and watch out for the conclusion of the Interpreter pattern!

As always, please share your comments and questions.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.