Command Pattern

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

Also Known as: Action, Transaction

Imaging this scenario: Client —> Invoker —> Service. In normal conditions when we want to call a method in Service we need to do this in Invoker:

public class Invoker{
    if (client_request_type_1) {call methods in Service}
    if (client_request_type_2) {call methods in Service}
    if (client_request_type_3) {call methods in Service}
}

This strategy obviously has its flaws when these types change or grow. Using the Command pattern, the Invoker and Service are decoupled.

Structure

command.jpeg

I omitted the dependencies of client with command, concrete commands and service.

Example

public interface Command{
    void execute();
}
 
public class FirstConcreteCommand implements Command{
    private Service service;
 
    public void execute(){
        service.doThis();
    }
}
 
public class SecondConcreteCommand implements Command{
    private Service service;
 
    public void execute(){
        service.doThat();
    }
}
 
public class Service{
    public void doThis(){}
    public void doThat(){}
}
 
public class Client{
   public static void main(String[] args){
       Service service = new Service();
       Command cmd1 = new FirstConcreteCommand(can pass Service);
       Command cmd2 = new SecondConcreteCommand(can pass Service);
 
       Invoker i = new Invoker(pass commands in);
 
       i.doOperation1();
       i.doOperation2();
   }
}
 
public class Invoker {
    private Command firstCommand;
    private Command secondCommand;
 
    public void doOperation1(){
        firstCommand.execute();
    }
 
    public void doOperation2(){
        secondCommand.execute();
    }
}

Another Example:

public interface Command {
    public Object execute();
}
 
//notice that this execute method has overwritten the return type
public class GetProduct1 implements Command {
    @Override
    public Product1 execute() {
        return ...
    }
}

In this example we are passing (can be injected using a DI framework via some config file) a list of commands to be executed. ServiceCommand is the abstract parent object:

        for (ServiceCommand command : serviceCommands) {
                  command.execute();
        }

In the following way we can Redo/Undo commands. Each command is an operation which has its undo/redo mechanism in itself:

public interface Command {
   void execute();
   void undo();
   void redo();
}
 
public class CommandManager {
   private LinkedList<Command> commandStack =  new LinkedList<Command>();
   private LinkedList<Command> redoStack =  new LinkedList<Command>();
 
   public void execute(Command command) {
      command.execute();
      commandStack.addFirst(command);
      redoStack.clear();
   }
 
   public void undo() {
      if (commandStack.isEmpty())
         return;
      Command command = commandStack.removeFirst();
      command.undo();
      redoStack.addFirst(command);
   }
 
   public void redo() {
      if (redoStack.isEmpty())
         return;
      Command command = redoStack.removeFirst();
      command.redo();
      commandStack.addFirst(command);
   }
}

Applicability

  • Support for redo and undo: execute method can store state for reversing or redoing its effects in the command itself. The Command interface must have an added UnExecute/ReExecute operation that reverses/re-executes the execute method. Executed commands are stored in a history list.
  • Command can parameterize objects by an action to perform. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks. Specially Java does not treat methods (functions) as first class objects and it's thus impossible to pass them around. Instead, you create an interface that can be passed around and that encapsulates the necessary information about how to call the original method. For example suppose that in a RemoteObject we want to login() and when successful "do another operation":
public class AnotherOperation implements Command{
     @Override
     public void execute() {
         //doing another operation
     }
 }
 
//In Client:
remoteObject.login(command);
 
//And in the login() function of RemoteObject we save a reference to command:
public void login(Command command) {
     ...    
     command.execute();  //callback
     ...
}

Related Patterns

  • Command Processor Pattern
  • You can assemble commands into a composite command using Composite Pattern. See MacroCommand in Command Processor Pattern
  • To avoid error accumulation while commands are being executed, unexecuted, and reexecuted repeatedly, commands need to store more information to ensure that objects are restored to their original state. The Memento Pattern can be applied to give the command access to this information without exposing the internals of other objects.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License