Command Design Pattern.

Command Design Pattern.


Command Design pattern is used to decouple Sender and Receiver.
Sender is totally unaware of Receiver's interface and Receiver is unaware of Sender.
Sender and Receiver communicates using command.



Command Design Pattern Example In Java.



Receiver.java
abstract class Receiver{
 public abstract void append(String data);
 public abstract String getContent();
 public abstract void copy(String copyData);
 public abstract void paste();
 public abstract void cut(int startIndex, int endIndex);
 public abstract void setContent(String content);
 public abstract String getName();
}

Notepad.java
class Notepad extends Receiver{
 private StringBuilder content;
 private String copyData;

 public Notepad(String init) {
  content = new StringBuilder(init);
 }
 public void append(String data){
  content.append(data);
 }
 public String getContent() {
  return content.toString();
 }
 public void copy(String copyData){
  this.copyData = copyData;
 }
 public void paste(){
  content.append(copyData);
 }
 public void cut(int startIndex, int endIndex){
  content = content.delete(startIndex, endIndex);
 }
 public void setContent(String content) {
  this.content = new StringBuilder(content);
 }
 public String getName() {
  return "Notepad";
 }
}

Wordpad.java
class Wordpad extends Receiver{
 private StringBuilder content;
 private String copyData;

 public Wordpad(String init) {
  content = new StringBuilder(init);
 }
 public void append(String data){
  content.append(data);
 }
 public String getContent() {
  return content.toString();
 }
 public void copy(String copyData){
  this.copyData = copyData;
 }
 public void paste(){
  content.append(copyData);
 }
 public void cut(int startIndex, int endIndex){
  content = content.delete(startIndex, endIndex);
 }
 public void setContent(String content) {
  this.content = new StringBuilder(content);
 }
 public String getName() {
  return "Wordpad";
 }
}

Command.java
interface Command{
 public void execute();
 public void redo();
}

Undo.java
interface Undo{
 public void undo();
}

CopyCommand.java
class CopyCommand implements Command{ 
 private String copiedData = "";

 public CopyCommand(String copiedData) {
  this.copiedData=copiedData;
 }
 public void execute() {
  System.out.println("Successfully copied: "+copiedData);
 }
 public void redo() {
  execute();
 }
 public String getCopiedData() {
  return copiedData;
 }
}

PasteCommand.java
class PasteCommand implements Command, Undo{
 private Receiver receiver=null;
 private String contentToPaste="";
 private String previousContent="";

 public PasteCommand(Receiver receiver, String contentToPaste) {
  this.receiver=receiver;
  this.contentToPaste=contentToPaste;
 }
 public void execute() {
  previousContent = receiver.getContent();
  receiver.copy(contentToPaste);
  receiver.paste();
  System.out.println("Data Pasted successfully in "+ receiver.getName() +" new content is : "+receiver.getContent());
 }
 public void undo() {
  receiver.setContent(previousContent);
  System.out.println("Done undoing and receiver "+ receiver.getName() +" data is : "+receiver.getContent());
 }
 public void redo() {
  execute();
 }
}
CutCommand.java
class CutCommand implements Command, Undo{ 
 private Receiver receiver=null;
 private String previousContent=null;
 private int startIndex=0;
 private int endIndex=0;

 public CutCommand(Receiver receiver, int startIndex, int endIndex) {
  this.receiver = receiver;
  this.startIndex = startIndex;
  this.endIndex = endIndex;
 }
 public void execute() {
  previousContent = receiver.getContent();
  receiver.cut(startIndex, endIndex);
  System.out.println("Data Cut successfully in "+ receiver.getName() +" new content is : "+receiver.getContent());
 }
 public void undo() {
  receiver.setContent(previousContent);
  System.out.println("Done undoing and receiver "+ receiver.getName() +" data is : "+receiver.getContent());
 }
 public void redo() {
  execute();
 }
}

CommandManager.java
class CommandManager{
 private Stack<Command> redoCommandStack = null;
 private Stack<Command> undoCommandStack = null;

 public CommandManager() {
  undoCommandStack = new Stack<Command>();
  redoCommandStack = new Stack<Command>();
 }

 public void setCommand(Command command) {
  undoCommandStack.add(command);
 }
 public void execute(){
  undoCommandStack.peek().execute();
 }
 public void undo(){
  if(!undoCommandStack.isEmpty()){
   redoCommandStack.push(undoCommandStack.peek());
   ((Undo)(undoCommandStack.pop())).undo();

  }else{
   System.out.println("Nothing to undo");
  }
 }
 public void redo(){
  if(!redoCommandStack.isEmpty()){
   redoCommandStack.pop().redo();
  }else{
   System.out.println("Nothing to redo");
  }
 }
}

CommandDesignPattern.java
public class CommandDesignPattern {

 public static void main(String[] args) {

  CommandManager commandManager = new CommandManager();
  Notepad notepadReceiver = new Notepad("Notepad, how are you?");
  Wordpad wordpadReceiver = new Wordpad("Wordpad, how are you?");

  //COPY
  Command copyCommand2 = new CopyCommand("good");
  commandManager.setCommand(copyCommand2);
  commandManager.execute();

  //PASTE
  Command pasteCommand = new PasteCommand(wordpadReceiver, ((CopyCommand)copyCommand2).getCopiedData());
  commandManager.setCommand(pasteCommand);
  commandManager.execute();

  //CUT
  Command copyCommand1 = new CutCommand(notepadReceiver, 2, 5);
  commandManager.setCommand(copyCommand1);
  commandManager.execute();

  //UNDO
  System.out.println("\nUndo::");
  commandManager.undo();
  System.out.println("Undo::");
  commandManager.undo();

  //REDO
  System.out.println("\nRedo::");
  commandManager.redo();
  System.out.println("Redo::");
  commandManager.redo();
 }
}


 

Real World Example.


Resturant is a classic example of Command Pattern.
Customer(Invoker) is not aware of Chef(Receiver) and they communicate via Waiter(Command Manager) by giving Menu Name(Commands) to them.
Customer doesn't need to know how to communicate directly with Chef.

Command Design Pattern used in JDK API.


java.lang.Runnable interface exhibits Command design pattern.

Thread pools
  • A typical, general-purpose thread pool class might have a public addTask() method that adds a work item to an internal queue of tasks waiting to be done. 
  • It maintains a pool of threads that execute commands from the queue. 
  • The items in the queue are command objects. 
  • Typically these objects implement a common interface such as java.lang.Runnable that allows the thread pool to execute the command even though the thread pool class itself was written without any knowledge of the specific tasks 

You may also like to see


Observer Design Pattern

When to use Builder design pattern

Adapter Design Pattern

Decorator Design Pattern

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Post a Comment