Monday, May 27, 2013

Command Pattern

Command Pattern

What is Command Pattern?

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

To understand command design pattern we should understand the associated key terms like client, command, command implementation, invoker, receiver.
  • Command is an interface with execute method. It is the core of contract.
  • A client creates an instance of a command implementation and associates it with a receiver.
  • An invoker instructs the command to perform an action.
  • A Command implementation’s instance creates a binding between the receiver and an action.
  • Receiver is the object that knows the actual steps to perform the action.

The following sequence diagram shows the relationship in a clearer way: 


Why need Command Pattern?
Allows the requester of a particular action to be decoupled from the object that performs the action

How to implement Command Pattern?
//Command
public interface Command
{
    public void execute();
}

//Concrete Command
public class LightOnCommand implementsCommand
{
  //reference to the light
  Light light;
 
  public LightOnCommand(Light light)
  {
      this.light = light;
  }
 
  public void execute()
  {
      light.switchOn();
  }
 
}

//Concrete Command
public class LightOffCommand implementsCommand
{
   //reference to the light
   Light light;
  
   public LightOffCommand(Light light)
   {
       this.light = light;
   }
  
   public void execute()
   {
       light.switchOff();
   }
  
}

//Receiver
public class Light
{
 private boolean on;

 public void switchOn()
 {
    on = true;
 }

 public void switchOff()
 {
    on = false;
 }

}

//Invoker
public class RemoteControl
{
  private Command command;

  public void setCommand(Command command)
  {
      this.command = command;
  }
 

  public void pressButton()
  {
      command.execute();
  }
 
}

//Client
public class Client
{
  public static void main(String[] args)
  {
      RemoteControl control = new RemoteControl();
     
      Light light = new Light();
     
      Command lightsOn = new LightsOnCommand(light);
      Command lightsOff = new LightsOffCommand(light);
     
      //switch on
      control.setCommand(lightsOn);
      control.pressButton();
     
      //switch off
      control.setCommand(lightsOff);
      control.pressButton();
 
  }


}

Another example


public interface Command {

       public abstract void execute();

}

public class OnCommand implements Command {

       private ConsumerElectronics ce;

       public OnCommand(ConsumerElectronics ce) {
              this.ce = ce;
       }

       public void execute() {
              ce.on();
       }
}

public class MuteAllCommand implements Command {
       List ceList;

       public MuteAllCommand(List ceList) {
              this.ceList = ceList;
       }

       @Override
       public void execute() {

              for (ConsumerElectronics ce : ceList) {
                     ce.mute();
              }

       }
}

public interface ConsumerElectronics {
       public abstract void on();

       public abstract void mute();
}

public class Television implements ConsumerElectronics {

       public void on() {
              System.out.println("Television is on!");
       }

       @Override
       public void mute() {
              System.out.println("Television is muted!");

       }
}

public class SoundSystem implements ConsumerElectronics {

       public void on() {
              System.out.println("Sound system is on!");
       }

       @Override
       public void mute() {
              System.out.println("Sound system is muted!");

       }
}

public class Button {
       Command c;

       public Button(Command c) {
              this.c = c;
       }

       public void click() {
              c.execute();
       }
}

public class UniversalRemote {
       public static ConsumerElectronics getActiveDevice() {
              // here we will have a complex electronic circuit :-)
              // that will maintain current device
              Television tv = new Television();
              return tv;
       }
}

public class DemoCommandPattern {
       public static void main(String args[]) {

              // OnCommand is instantiated based on active device supplied by Remote
              ConsumerElectronics ce = UniversalRemote.getActiveDevice();
              OnCommand onCommand = new OnCommand(ce);
              Button onButton = new Button(onCommand);
              onButton.click();

              Television tv = new Television();
              SoundSystem ss = new SoundSystem();
              List all = new ArrayList();
              all.add(tv);
              all.add(ss);
              MuteAllCommand muteAll = new MuteAllCommand(all);
              Button muteAllButton = new Button(muteAll);
              muteAllButton.click();

       }

}

Collusion

  • The applicability of the Command design pattern can be found in these cases below:
  • parameterizes objects depending on the action they must perform
  • specifies or adds in a queue and executes requests at different moments in time
  • offers support for undoable actions (the Execute method can memorize the state and allow going back to that state)
  • structures the system in high level operations that based on primitive operations
  • decouples the object that invokes the action from the object that performs the action. Due to this usage it is also known as Producer - Consumer design pattern.
References

0 comments:

Post a Comment