One of my friends requested me to write a post on Command design pattern. I replied, your wish is my Command!
Command design pattern is a behavioral pattern and is also known as an action or transaction pattern. It decouples the object that invokes the operation from the one having the knowledge to perform it. The invoker/requester and the receiver/doer are loosely coupled. Invoker object only knows how to issue/invoke the request (It doesn't know how the request will be carried out). Receiver (at the receiving end ;-) ) knows how to carry out a task/operation. Command objects connect these two pieces(invoker and receiver); let's refer this tri-chemistry as iCr.
Command design pattern is a behavioral pattern and is also known as an action or transaction pattern. It decouples the object that invokes the operation from the one having the knowledge to perform it. The invoker/requester and the receiver/doer are loosely coupled. Invoker object only knows how to issue/invoke the request (It doesn't know how the request will be carried out). Receiver (at the receiving end ;-) ) knows how to carry out a task/operation. Command objects connect these two pieces(invoker and receiver); let's refer this tri-chemistry as iCr.
Invoker --> {Command} --> Receiver
Encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Command DP encapsulate a request as an object and pass it to an invoker, wherein the invoker does not knows how to service the request but uses the encapsulated command to perform an action. It takes an operation and its arguments and wraps them up in an object to be executed, logged, etc.
Invoker issues a request by calling execute method on the command. Then, concrete command invokes operation on its receiver to carry out a request. Below diagram shows sequence of events.
Ref : Gang of four design pattern |
Implementation
Let's cover briefly the actors or components involved in this pattern.
- Command: Defines an interface for executing an operation
- Concrete Command: Binds a specific command to receiver
- Invoker: Invokes or initiates command (stores concrete command object)
- Receiver: Actual object which performs operation
- Client: Creates concrete command and sets corresponding receiver
Clearly understanding role of all above is incredibly important. Instead of taking specific example and then illustrating this pattern, let's stick with above names itself. If the relationship among them is clear; visualizing a real example won't be difficult.
package command.pattern;
/**
* Command or action class; usually just has single method
*/
public interface Command {
public void execute();
}
package command.pattern;
/**
* Specific command implementation. There will be one class for each command
* like LightOnCommand, LightOffCommand, UndoCommand etc.
*
* Encapsulates the receiver.
*/
public class ConcreteCommand implements Command {
private Receiver rec;
public ConcreteCommand(Receiver rec) {
this.rec = rec;
}
@Override
public void execute() {
rec.performTask();
}
}
package command.pattern;
/**
* Class responsible of doing the real work : turn on a light, cook food or
* anything for you
*/
public class Receiver {
public void performTask() {
System.out.println("inside receiver");
// do the assigned work
}
}
package command.pattern;
/**
* Takes instance of command and calls execute method to perform the work
* Invoker doesn't know how the work will be done
*/
public class Invoker {
private Command command;
public void setCommand(Command com) {
this.command = com;
}
public void performRequest() {
command.execute();
}
}
package command.pattern;
/**
* Client class which connects the dots
*/
public class Client {
public static void main(String[] args) {
Command command = new ConcreteCommand(new Receiver());
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.performRequest();
}
}
MVC framework, Struts uses command pattern to service HTTP requests. Struts provides a Servlet known as Action Servlet, which handles HTTP request and then invokes an application specific action. As a developer we don't need to bother about how things work under the hood. We just need to know how to map an HTTP request to a Struts action and how to implement that action. Similarly, Swing framework also uses this pattern to handle UI events on buttons and menu items.
Undo/Redo support
As the intent of the pattern clearly explains, this pattern can be used for undo or redo operations as well. To support it, the Command will have to maintain the state . For undo, application will have to store the command that was executed last. This way application can store any amount of past actions and call those command in reverse direction to achieve multiple undo commands. Similarly, keep calling in forward direction to achieve redo. If list of all past actions/commands are stored, then it can be used for logging as well when the system crash.
--------------------------> redo
{ command1, command2, command3, .... ....commandn}
<------------------------------- undo
Below class shows a command which supports undo operation. The Command interface has to provide abstract undo() method along with execute().
<------------------------------- undo
Below class shows a command which supports undo operation. The Command interface has to provide abstract undo() method along with execute().
package command.pattern;
/**
* Command to turn on light
*/
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
----
pattern..pattern...pattern !!!
No comments:
Post a Comment