A java blog with a collection of examples and tutorials on Java and related technologies. (Under maintenance with continuous updates) Be in touch with java jazzle or k2java.blogspot.com.
Friday, May 20, 2011
Chain of Responsibility pattern
Command pattern
Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or
log requests, and support undo-able operations
Terms you must know before we start on it
Three terms always associated with the command pattern are client, invoker and receiver. The client instantiates the command object and provides the information required to call the method at a later time. The invoker decides when the method should be called. The receiver is an instance of the class that contains the method's code.
Advantage of Command Pattern
Using the command pattern helps you to :
- Decouple the object that invokes the operation from the one that performs the action.
described earlier. - Assemble commands into a composite command. An example is the MacroCommand class. Composite commands are an instance of the Composite pattern.
- Add new Commands, without having to change existing classes.
Command Pattern in UML
Make Operation and Operand interface for greater flexibility.
Implementing Command Pattern in java
Consider the class diagram:
The following is a simple description of each of the elements of the above diagram, followed by a simple implementation.
Client: The client is responsible for creating the Command object and setting it's reciever.
public class ClientApp {
public static void main(String[] args) {
Receiver rec = new Receiver();
Command incCommand = new IncrementCommand(rec);
Command decCommand = new DecrementCommand(rec);
Invoker invoker = new Invoker();
invoker.setDecCommand(decCommand);
invoker.setIncCommand(incCommand);
invoker.addRequest();
invoker.addRequest();
invoker.removeRequest();
System.out.println(rec.getValue());
}
}
Invoker: The Invoker acts as a placeholder for the Command object and invokes the execute method on the Command. In case of undoable commands, it stores the command in a stack (for multi-level undo, or just the command for single level undo), before executing the command.
public class Invoker {
Stack<Command> commands;
Command incCommand;
Command decCommand;
public Invoker() {
commands = new Stack<Command>();
}
public void setIncCommand(Command command) {
incCommand = command;
}
public void setDecCommand(Command command) {
decCommand = command;
}
public void undoAll() {
Command cmd = null;
while (!commands.empty()) {
cmd = commands.pop();
cmd.undo();
}
}
public void addRequest() {
incCommand.execute();
commands.add(incCommand);
}
public void removeRequest() {
decCommand.execute();
commands.add(decCommand);
}
public void commit() {
commands = new Stack<Command>();
}
}
Receiver: The object that performs the operations associated with carrying out a request. Any class may serve as a Receiver.
public class Receiver {
private int value;
public Receiver() {
value = 0;
}
public void increment() {
++value;
}
public void decrement() {
--value;
}
public int getValue() {
return value;
}
}
Command: The command object represents the request operation. The command implements execute() method, which invokes the corresponding operations on the Reciever. This defines a binding between a Receiver object and an action.
public interface Command {
public void execute();
public void undo();
}
public class IncrementCommand implements Command {
Receiver receiver;
public IncrementCommand(Receiver rec) {
receiver = rec;
}
public void execute() {
receiver.increment();
}
public void undo() {
receiver.decrement();
}
}
public class DecrementCommand implements Command {
Receiver receiver;
public DecrementCommand(Receiver receiver) {
this.receiver = receiver;
}
public void execute() {
receiver.decrement();
}
public void undo() {
receiver.increment();
}
}
Additional Notes
- A command can have a wide range of abilities from a simple interface between the client and receiver to being a receiver itself.
- When supporting multi-level undo, a command may store state information, which mean that, with each execute(), you have to copy the state of the command at that time. In such cases a copy of the command has to be added to the history stack.
Interpreter Pattern
Visitor pattern
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Visitor is guided by the Traverser to gather state from all of the objects in the Composite.
Once the state has been gathered, the Client can have the Visitor perform various operations on the state. When new functionality is required, only the Visitor must be enhanced.
Class hierarchy for Visitor Pattern
The idea is to have two class hierarchies
- One for the elements being operated on, where each element has an "accept" method that takes a visitor object as an argument
- One for the visitors that define operations on the elements. Each visitor has a visit() method for each element class.
- Visitor: Declares the visit method.
- ConcreteVisitor: An implementation of the Visitor interface. May also store state if required.
- Element (or Visitable): The interface that declares the accept method. The accept method invokes the visit method passing itself as an argument.
- ConcreteElement: Element of the object structure. Has to implement accept method (implements Element).
When to use Visitor Pattern
Use the Visitor pattern when- There is a need perform operations that depend on concrete classes of an object structure, and the structure may contain classes of objects with differing interfaces.
- Distinct and unrelated operations must be performed on objects in an object structure, and you want to avoid distributing/replicating similar operations in their classes
- The classes defining the object structure rarely change, but new operations may be added every once in a while.
Visitor Benefits
1. Allows you to add operations to a Composite structure without changing the structure itself. 2. Adding new operations is relatively easy. 3. The code for operations performed by the Visitor is centralized.Visitor Drawbacks:
1. Encapsulation of the Composite classes is broken when the Visitor is used. 2. Because the traversal function is involved, changes to the Composite structure are more difficult.Visitor Pattern and Double Dispatch
Double dispatch is a mechanism that allows a function call to change depending on the runtime types of multiple objects involved in the call. In single dipatch a call like Integer.compareTo(Object o), the actual function call depends only on the calling object (the Integer object here). In double dispatch, the actual call may also depend on the object being passed as a parameter to the compareTo method. The most common programming languages (except for LISP) do not have a way for implementing double dispatch. But you may implement double dispatch in these programming languages using the Visitor pattern. You can see the implementation in the following example. Here the call to accept depends not only on the type of object on which it is called (MyLong or MyInteger) but also on the parameter that is being passed to it (AddVisitor and SubtractVisitor).Example of Visitor Pattern in Java
To implement the Visitor pattern, you create a Visitor interface for the visitor, and a Visitable interface for the item or collection to be visited. Declaring the interfacesinterface Visitor { public int visit(MyInteger wheel); public int visit(MyLong engine); } interface Visitable { public int accept(Visitor visitor); }
class MyInteger implements Visitable { private int value; MyInteger(int i) { this.value = i; } public int accept(Visitor visitor) { return visitor.visit(this); } public int getValue() { return value; } } class MyLong implements Visitable { private long value; MyLong(long l) { this.value = l; } public int accept(Visitor visitor) { return visitor.visit(this); } public long getValue() { return value; } }
class SubtractVisitor implements Visitor { int value; public SubtractVisitor(int value) { this.value = value; } public int visit(MyInteger i) { System.out.println("Subtract integer"); return (i.getValue() - value); } public int visit(MyLong l) { System.out.println("Subtract long"); return ((int) l.getValue() - value); } } class AddVisitor implements Visitor { int value; public AddVisitor(int value) { this.value = value; } public int visit(MyInteger i) { System.out.println("Adding integer"); return (value + i.getValue()); } public int visit(MyLong l) { System.out.println("Adding long"); return (value + (int) l.getValue()); } }
public class VisitorTest { public static void main(String[] args) { AddVisitor cv = new AddVisitor(10); SubtractVisitor sv = new SubtractVisitor(10); MyInteger i = new MyInteger(20); MyLong l = new MyLong(20); System.out.println(i.accept(cv)); System.out.println(l.accept(cv)); System.out.println(i.accept(sv)); System.out.println(l.accept(sv)); } }
Mediator pattern
Define an object that encapsulates details and other objects interact with such object.The relationship are loosely decoupled.
Wikipedia Says:
Mediator Pattern is a software design pattern that provides a unified interface to a set of interfaces in a subsystem.This pattern is considered a behaviour pattern due to the way it can alter the program's running behaviour.
Usually a program is made up of a (sometimes large) number of classes. So the logic and computation is distributed among these classes. However, as more classes are developed in a program, especially during maintenance and/or refactoring, the problem of communication between these classes may become more complex. This makes the program harder to read and maintain. Furthermore, it can become difficult to change the program, since any change may affect code in several other classes.
With the mediator pattern communication between objects is encapsulated with a mediator object. Objects no longer communicate directly with each other, but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby lowering the coupling.
Mediator class promotes looser coupling between a number of other classes.It consists of a mediator class that is the only class that has detailed knowledge of the methods of other classes.
Promotes the many-to-many relationships between interacting peers to "full object status".
When to use Mediator Pattern?
- Use the Mediator Pattern to centralize complex communications and control between related objects.
- Mediator is commonly used to coordinate realted GUI components.
Advantages
- Increases the reusability of the objects supported by the Mediator by decoupling them from the system.
- Simplfies maintenance of the system by centralizing control logic.
- Simplifies and reduces the variety of messages sent between objects in the system.
- Partition a system into pieces or small objects.
- Centralize control to manipulate participating objects.
- Most of the complexity involved in managing dependencies is shifted from other objects to the Mediator object.This makes other objects easier to implement and maintain.
Disadvantages
- A drawback of mediator pattern is that without proper design, the Mediator object itself can become overly complex.
Mediator defines an object that controls how a set of objects interact.Loose coupling between collegue objects is achieved by having collegues communicate with the Mediator,rather than with each other.
Let us look at an example...
Example Code for Mediator Pattern
In Outlook we can create some rules and alerts. Similarly for gmail we can have filters.
We can have rules like
FromRule : If a mail comes from xxx, send it to yy folder.
ToRule : If my name is in To list of the received mail, send it to yy folder.
CcRule: If my name is in Cc list of the received mail, send it to yy folder.
Let us look how we can implement the above through Mediator pattern.
So lets say we are providing these rules. So first we create a basic Rule class, which is base class of all these rules.
Rule
public class Rule {
private String text;
private Boolean isActivated=Boolean.FALSE;
public Boolean getIsActivated() {
return isActivated;
}
public void setIsActivated(Boolean isActivated) {
this.isActivated = isActivated;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Command
Now these rules need command to be executed
public interface Command {
void execute();
}
Getting the rules
public class ToRule extends Rule implements Command {
RuleMediator mediator;
ToRule(RuleMediator mediator) {
this.mediator = mediator;
mediator.selectToRule(this);
}
public void execute() {
mediator.createToRule();
}
}
public class CcRule extends Rule implements Command {
RuleMediator mediator;
CcRule(RuleMediator mediator) {
this.mediator = mediator;
mediator.selectCcRule(this);
}
public void execute() {
mediator.createCcRule();
}
}
Mediator class
public class RuleMediator {
FromRule fromRule;
ToRule toRule;
CcRule ccRule;
void selectFromRule(FromRule fromRule) {
this.fromRule = fromRule;
}
void selectToRule(ToRule toRule) {
this.toRule = toRule;
}
void selectCcRule(CcRule ccRule) {
this.ccRule = ccRule;
}
void createFromRule() {
fromRule.setIsActivated(true);
toRule.setIsActivated(false);
ccRule.setIsActivated(false);
fromRule.setText("If a mail comes from xxx
send to yy folder...");
}
void createToRule() {
fromRule.setIsActivated(false);
toRule.setIsActivated(true);
ccRule.setIsActivated(false);
toRule.setText("If my name is in To list,
send to yy folder...");
}
void createCcRule() {
fromRule.setIsActivated(false);
toRule.setIsActivated(false);
ccRule.setIsActivated(true);
toRule.setText("If my name is in Cc list,
send to yy folder...");
}
}
Mediator Demo
public class MediatorDemo {
public static void main(String[] args) {
RuleMediator mediator = new RuleMediator();
FromRule fromRule = new FromRule(mediator);
ToRule toRule = new ToRule(mediator);
CcRule ccRule = new CcRule(mediator);
mediator.selectFromRule(fromRule);
mediator.selectToRule(toRule);
mediator.selectCcRule(ccRule);
fromRule.execute();
System.out.println(fromRule.getText());
System.out.println("from Rule is enabled
--> "+fromRule.getIsActivated());
System.out.println("to Rule is enabled
--> "+toRule.getIsActivated());
}
}
Related Patterns
Facade: which abstracts a subsystem to provide a more convenient interface,and its protocol is uni-directional,whereas a mediator enables co-operative behavior and its protocol is multidirectional.
Command: Which is used to coordinate functionality.
Observer: which is used in mediator pattern to enhance communication.
Rules of Thumb
Chain of Responsibility,Command,Mediator and Observer,address how you can decouple senders and receivers,but with different trade-offs.Chain of Responsibility passes a sender request along a chain of potential receivers.Command normally specifies a sender-receiver connection with a subclass.Mediator has senders and receivers reference each other indirectly.Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.[GoF, p347]
Mediator and Observer are competing patterns.The difference between them is is that Observer distributes communication by introducing "observer" and "subject" objects,whereas a Mediator object encapsulates the communication between other objects.We've found it easier to make reusable Observers and Subjects than to make reusable Mediators.[GoF, p346]
On The other hand Mediator can leverage Observer for dynamically registering collegues and communicating with them. [GoF, p282]
Mediator is similar to Facade in that it abstracts functionality of existing classes.Mediator abstracts/centralizes arbitrary communication between colleague objects,it routinely "adds value",and it is known/referenced by the collegue objects.In contrast,Facade defines a similar interface to a subsystem,it doesnot add new functionality,and it is not known by the subsystem classes.(i.e a uni-directional protocol where it makes requests of the subsystem classes.(i.e it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice-versa.) [GoF,p193]
Memento Pattern
Memento Pattern provides an ability to record an object internal state without violating encapsulation and reclaim it to previous state later without knowledge of the original object.
Participants in Memento Pattern
Memento Pattern is used by two objects.The originator and a caretaker.The originator is some object that has an internal state.Caretaker is going to perform some action to the originator,but wants to be able to undo the change.
- Caretaker first asks the originator for a memento object.
- Then it does what ever operations it was going to perform.
- To rollback the state before the operations,it returns the memento object to the originator.
- Memento object itself is an opaque object(one which the caretaker can not,or should not change.)
The solution is to wrap the state that you wish to preserve in an object, using Memento. A Memento is an object that contains the current internal state of the Originator object. Only the Originator can store and retrieve information from the Memento. To the outside world the Memento is just an arbitrary object.
Structure Summary
- Identify a class that needs to be able to take a snapshot of its state.(the originator role.)
- Design a class that does nothing more than accept and return this snapshot.(The memento role).
- Caretaker Role asks the Originator to return a Memento and cause the Originator's previous state to be restored of desired.
- Notion of undo or rollback has now been objectified(i.e promoted to full object status).
Discussion
Client requests a Memento from the source object when it needs to checkpoint the source object's state.Source Object initializes the Memento with a characterization of its state.The client is the care taker of the Memento,but only the source object can store and retrieve information from the Memento(The Memento is opaque to the client and all other objects.)If the client subsequently needs to "rollback" the source object's state,it hands the Memento back to the source object for reinstatement.
An unlimited "undo" and "redo" capability can be readily implemented with a stack of Command objects and a stack of Memento objects.
The Memento design pattern defines three distinct roles:
Originator: the object that knows how to save itself.
Caretaker: the object that knows why and when the originator needs to save and restore itself.
Memento: The lock box that is written and read by the originator and shepherded by the Caretaker.
Example
The Memento captures and externalizes an object's internal state so that the object can later be restored to that state. This pattern is common among do-it-yourself mechanics repairing drum brakes on their cars. The drums are removed from both sides, exposing both the right and left brakes. Only one side is disassembled and the other serves as a Memento of how the brake parts fit together. Only after the job has been completed on one side is the other side disassembled. When the second side is disassembled, the first side acts as the Memento. [Michael Duell, "Non-software examples of software design patterns", Object Magazine, Jul 97, p54]
Checklist
1. Identify the roles of "care taker" and "originator".
2. Originator creates a Memento and copies its state to that Memento.
3. Caretaker holds on to(but cannot peek into) the Memento.
4. Caretaker knows when to rollback the originator.
5. Originator reinstantes itself using the saved state in that Memento.
Rules of thumb
Command and Memento act as magic tokens to be passed around and invoked at a later time.In Command,the token represents a request,in Memento,it represents the internal state at a particular time.Polymorphism is important to Command but not to Memento because its interface is so narrow that a memento can only be passed as a value. [GoF, p346]
Command can use Memento to maintain the state required for an undo operation.[GoF, p242]
Memento can be used in conjuction with Iterator.An Iterator can use a Memento to capture the state of iteration.Iterator stores the Memento internally.[GoF, p271]
Classic examples of the memento pattern include the seed of a pseduorandom number generator.
Matthew Heaney says,
A memento is an alternate representation of another object,often in a format suitable for transmission across an external interface.
And programmers should be familar with this pattern,because it's used by the random number library to save and restore the state of a generator.
If we identify,This pattern is similar lot to serialization.As we know Serialization is done where the source object is stored and resurrected by another object and happens between different invocations of an application or between applications.Here the source object is still there and all that happens is state change. - Raptor Balaji
When to use Memento Pattern?
Use Memento Pattern when you need to be able to return an object to one of its previous states; for instance if your user requests and 'undo'.
Intent:
1. Saving the important state of system's key object.
2. Maintaining the key object's encapsulation.
Keeping the Single Responsibility Principle in mind, it is also a good idea to keep the state that you are saving seperate from the key object.
This seperate object that holds the state is known as the Memento object.
Using Memento Pattern,we can ask for an object for its current state,and it can track whatever changes are made using special semantics,rather than dumping the entire state and rereading later.
Example Code For Memento Pattern
Below example describes an implementation of Memento pattern.
Originator Class
class Originator {
private String state;
public void set(String state) {
System.out.println("Originator: Setting state to" + state);
this.state=state;
}
public Object saveToMemento() {
System.out.println("Originator: Saving to memento");
return new Memento(state);
}
public void restoreFromMemento(Object o) {
if(o instanceof Memento) {
Memento m=(Memento)o;
state=m.getSavedState();
System.out.println("Originator:State after restoring from Memento:" + state);
}
}
private static class Memento {
private String state;
public Memento(String stateToSave) {
state=stateToSave;
}
public String getSavedState() {
return state;
}
}
}
CareTaker
class CareTaker {
private List<Object> savedStates=new ArrayList<Object>();
public void addMemento(Object m) {
savedStates.add(m);
}
public Object getMemento(int index) {
return savedStates.get(index);
}
}
MementoPatternDemo
public class MementoPatternDemo {
public static void main(String[] args) {
CareTaker careTaker=new CareTaker();
Originator originator=new Originator();
originator.set("State1");
originator.set("State2");
careTaker.addMemento(originator.saveToMemento());
originator.set("State 3");
careTaker.addMemento(originator.saveToMemento());
originator.set("State 4");
originator.restoreFromMemento(careTaker.getMemento(1));
}
}
Advantages of Memento Pattern
1. Keeping the saved state external from key object helps to maintain cohesion.
2. Keeps the key object's data encapsulated.
3. Provides easy-to-implement recovery capability.
Drawbacks
1. Saving and restoring state may be time consuming.
2. In Java consider using serialization to save a system's state.
3. It exposes the internal structure of your object.
4. It enables the other object to arbitrarily change the state of your object.