The Command Design Pattern wraps a request in an object as command and pass it to a command invoker object. When invoker receives a request, it looks for the appropriate object which is capable of handling this request and passes the command to the corresponding object for execution. This allows clients to be parameterized with different requests.
In command pattern, a client just gives instructions to invokes without knowing how it is going to be executed. It supports decoupling between a client object which request a task and the receiver object which actually performs the task. This pattern is not focused on the sequence of the tasks stored, but on hiding the details/implementation of the actions performed.
- Define a Command interface having an execute method execute().
- All command objects must implements a Command interface. The execute method delegates the request to a receiver to execute the command.
- A receiver class holds the logic of performing any specific task requested as command. It is called from execute method of command object.
- The client creates a set of command objects and associates receiver with it. Client passes commands to invoker to store it. Later, client calls invoker to execute the commands.
Advantages of Command Pattern
- A command decouples the command invoker object and the one who actually perform the command. The invoker invokes the command without knowing about of details of who or how it is going to be executed.
- For a invoker, all command objects are same. It just call the execute method of every command.
- We can add a new command any time without any modification in invoker or client implementation.
When we should use Command Pattern
- When we want to keep historical records of the actions performed on an object, where every action is implemented as a command.
- When we implement a sequence of tasks as workflow. We can model every task as a command and execute them in a specific sequence.
- When we want to implement object oriented call back.
- When we want to decouple the invoker and the receiver.
Implementation of Command Design Pattern
- Define a Command interface having an execute method execute().
- All command objects must implements a Command interface. The execute method delegates the request to a receiver to execute the command.
- A receiver class holds the logic of performing any specific task requested as command. It is called from execute method of command object.
- The client creates a set of command objects and associates receiver with it. Client passes commands to invoker to store it. Later, client calls invoker to execute the commands.
Command.java public interface Command { public void execute(); }
DrawCircle and DrawRectangle are concrete implementation of Command interface.
DrawCircle .java public class DrawCircle implements Command { private ShapeDrafter drafter; public DrawCircle(ShapeDrafter drafter){ this.drafter = drafter; } public void execute(){ drafter.drawCircle(); } }
DrawRectangle.java public class DrawRectangle implements Command { private ShapeDrafter drafter; public DrawRectangle(ShapeDrafter drafter){ this.drafter = drafter; } public void execute(){ drafter.drawRectangle(); } }
ShapeDrafter is the receiver class which draws circle and rectangle.
ShapeDrafter.java public class ShapeDrafter { public void drawRectangle(){ System.out.println("Drawing a Rectangle on Screen"); } public void drawCircle(){ System.out.println("Drawing a Circle on Screen"); } }
CommandInvoker.java import java.util.List; import java.util.ArrayList; public class CommandInvoker { private List<Command> commandList = new ArrayList<Command>(); public void addCommand(Command c){ commandList.add(c); } public void executeCommands(){ for(Command c : commandList){ c.execute(); } } }
CommandPatternExample class creates command objects and pass it to CommandInvoker for execution.
public class CommandPatternExample { public static void main(String args[]){ ShapeDrafter drafter = new ShapeDrafter(); Command rectangleCommand = new DrawRectangle(drafter); Command circleCommand = new DrawCircle(drafter); CommandInvoker invoker = new CommandInvoker(); invoker.addCommand(circleCommand); invoker.addCommand(rectangleCommand); invoker.executeCommands(); } }
Output
Drawing a Circle on Screen Drawing a Rectangle on Screen