Sunday, March 14, 2010

Command design pattern

The command pattern basically has client, command, invoker and the receiver. The pattern encapsulates request (command) as an object. It decouples the client from the receiver. The requests are defined through concrete commands which encapsulate the receiver and implement the command interface containing a single execute() method in it. It uses an invoker with a standardised interface (execute()) to invoke the request on the receiver. The invoker has no knowledge of the receiver. The concrete command it invokes knows about the receiver, the action to invoke on it and the parameters to be passed to it. We are basically issuing requests to objects without knowing anything about the receiver of the object or the method being invoked on it.

We will illustrate it with an example whose UML is in Fig1.


The walk through the example is self-explanatory.

package raj;

public class TestCommand {

public static void main(String[] arg) {
// First illustrate the tight coupling of Horse class
Horse horse = new Horse();
horse.eat();

/* Obviously we could do this with other classes too
* but we want to decouple the receiver of the action
* from the client using action commands invoked by an
* intermediary, the Invoker.
*/
// create the command we want to invoke
Command command = new EatCommand(new Horse());
// create the invoker
Invoker invoker = new Invoker();
// Tell the invoker about the command we want to execute
invoker.setCommand(command);
// execute the EatCommand via the invoker
invoker.execute();
// change the animal to tiger and execute
command = new EatCommand(new Tiger());
invoker.setCommand(command);
invoker.execute();
// illustrate how we can do no action
invoker.setCommand(new NoCommand());
invoker.execute();
// create a different type of command on a different class
// illustrate the action can do multiple things
invoker.setCommand(new ExamineCommand(new Vet()));
invoker.execute();
// pass parameters to command
invoker.setCommand(new PaperWorkCommand(new Clerk(), "Efficienly"));
invoker.execute();
}
}

interface Command {

public void execute();
}

class Invoker implements Command {

Command command;

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

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

class NoCommand implements Command {

public void execute() {
}
}

class EatCommand implements Command {
/* the key thing is that the command knows about the receiver
* (contains Animal in this case)
* and the type of action to take on it (run eat() method)
*/

Animal animal;

EatCommand(Animal animal) {
this.animal = animal;
}

public void execute() {
animal.eat();
}
}

class ExamineCommand implements Command {

Vet vet;

ExamineCommand(Vet vet) {
this.vet = vet;
}

public void execute() {
vet.openSurgery();
vet.examine();
vet.closeSurgery();
}
}

class PaperWorkCommand implements Command {

Clerk clerk;
String efficiency;

PaperWorkCommand(Clerk clerk, String efficiency) {
this.clerk = clerk;
this.efficiency = efficiency;
}

public void execute() {
clerk.pushPaper(efficiency);
}
}

class Animal {

public void eat() {
System.out.println("Eating generically");
}
}

class Horse extends Animal {

public void eat() {
System.out.println("Eating grass");
}
}

class Tiger extends Animal {

public void eat() {
System.out.println("Eating meat");
}

public void attack() {
System.out.println("Killing a prey");
}
}

class Vet {

public void examine() {
System.out.println("Examine an animal");
}

public void openSurgery() {
System.out.println("Surgery opened");
}

public void closeSurgery() {
System.out.println("Surgery closed");
}
}

class Clerk {

public void pushPaper(String efficiency) {
System.out.println("Doing paperwork " + efficiency);
}
}

Note that strategy pattern had also encapsulated behaviour.


No comments:

Post a Comment