Command design pattern

Type : Behavioral Design Pattern


Summary

Command pattern separates the client which invokes a method from the object which contains the method.


Important points

Command pattern decouples requestor (Invoker) of the action from the object that perform

the action (Receiver).

Command pattern can be used to do undo operations.

Command pattern is useful when a history of requests is needed.

Command pattern is useful when  \we need callback functionality

Advantages
it decouples the client from the actual class who performs the operation.
We can create new commands to have new behaviour.
Undo operations can be designed with command pattern.

Disadvantages
It increases the number of Classes.
If the Receiver class changes we would need to change the Command Class.

Details

Different  Objects participating  in the pattern are,

Command - declares an interface for executing an operation;

ConcreteCommand - extends the Command interface, implementing the execute method by invoking the corresponding operations on Receiver. It defines a link between the Receiver and the action.

Client - creates a ConcreteCommand object and sets its receiver;

Invoker - Holds Command Object and executes execute() method of the command object;

Receiver - knows how to perform the operations;

Example

This example is about a Remote control receiver say like TV which accepts some kind of commands like turn on, turn of change channel etc.. 

Receiver is RemotecontrolReceiver Object which knows how to perform.
Invoker is DeliveryAgentInvoker Object which gets Command object and call execute() method on them.
Client can be assume like a remote control which actually has some action buttons (Command Objects ) and set them to Invoker (DeliveryAgentInvoker)

We have three command objects TurnOffCommand, TurnOnCommand and ChangeChannelCommand.

Client sets the Commands in Invoker Object  and calls method in Invoker.

Class Diagram



Sample Code



// receiver Object
public class RemotecontrolReceiver {

 String currentChannel = "";
  
 public void turnOn() {
   System.out.println("turn on");
 }
 
 public void turnOff() {
   System.out.println("turn off");
 }

 public void changeChannel(String channel) {
   System.out.println("tune to channel " + channel);
   this.currentChannel = channel;
 }
 
}


// interface command
public interface Command {

  public void execute();

  public void undo();

}

public class TurnOffCommand implements Command {

  RemotecontrolReceiver remote;

  public TurnOffCommand(RemotecontrolReceiver o) {
    remote = o;
  }

  @Override
  public void execute() {
    this.remote.turnOff();
  }

  @Override
  public void undo() {

  }

}


public class TurnOnCommand implements Command {

  RemotecontrolReceiver remote;

  public TurnOnCommand(RemotecontrolReceiver o) {
    remote = o;
  }

  @Override
  public void execute() {
    remote.turnOn();
  }

  @Override
  public void undo() {
    
  }
  
}


// Invoker
public class DeliveryAgentInvoker {
  
  List deliveries = new ArrayList<>();

  public DeliveryAgentInvoker() {}

  public void deliver(Command orderDeliver) {
    deliveries.add(orderDeliver);
    orderDeliver.execute();
  }

}

public class Client {

  public static void main(String[] args) {
    
    RemotecontrolReceiver order = new RemotecontrolReceiver();
    DeliveryAgentInvoker dA = new DeliveryAgentInvoker();
    
    TurnOnCommand aC = new TurnOnCommand(order);
    TurnOffCommand rC = new TurnOffCommand(order);
    ChangeChannelCommand change = new ChangeChannelCommand(order, "2");
   
    dA.deliver(aC);
    dA.deliver(rC);
    dA.deliver(change);

  }

}

Comments

Popular posts from this blog

Converting Java Map to String

Difference between volatile and synchronized

Invoking EJB deployed on a remote machine