CSC/ECE 517 Fall 2012/ch2b 2w40 sn: Difference between revisions
Line 265: | Line 265: | ||
The caretaker first asks the originator for a memento object. Then it does the work it was slated to do. To roll back to the state before the operations, it returns the memento object to the originator. The memento object itself is an opaque object (one which the caretaker cannot change). When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.In other words, the memento pattern can be viewed as maintaining a "checkpoint" so that the originator can easily rollback to the previous checkpoint.[http://sourcemaking.com/design_patterns/memento] | The caretaker first asks the originator for a memento object. Then it does the work it was slated to do. To roll back to the state before the operations, it returns the memento object to the originator. The memento object itself is an opaque object (one which the caretaker cannot change). When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.In other words, the memento pattern can be viewed as maintaining a "checkpoint" so that the originator can easily rollback to the previous checkpoint.[http://sourcemaking.com/design_patterns/memento] | ||
The following diagram illustrates the memento pattern: | The following diagram illustrates the memento pattern:<br/> | ||
[[File:Memento.jpg]] | [[File:Memento.jpg]] | ||
Revision as of 05:52, 19 November 2012
Introduction to Command Pattern
The command pattern is one of the most used behavioral design patterns. The main concept of the pattern is an object which can be used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters.
The command pattern has been often associated with these terms 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.
The intent of the Command pattern can be listed as:
- encapsulate a request in an object
- allows the parametrization of clients with different requests
- allows saving the requests in a queue
A Java Example
As the figure above suggests the integral parts of the command pattern are the client,invoker and the receiver.The command part is split into two parts-the interface and the concrete command. The examples are explored more in the below example. This is the command interface which contains the skeleton code of the command pattern containing exactly one method called execute.
//Command public interface Command { public void execute(); }
//Concrete Command public class LightOnCommand implements Command { //reference to the light Light light; public LightOnCommand(Light light) { this.light = light; } public void execute() { light.switchOn(); } }
//Concrete Command public class LightOffCommand implementsCommand { //reference to the light Light light; public LightOffCommand(Light light) { this.light = light; } public void execute() { light.switchOff(); } }
LightOnCommand and LightOffCommand represents the concrete command classes that the client shall use.
Light is the receiver class which contains the commands to be executed.
//Receiver public class Light { private boolean on; public void switchOn() { on = true; } public void switchOff() { on = false; } }
The invoker is the one which actually which calls the execute method of the command class. This also has a accessor method which sets the current command to be executed.
//Invoker public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); } }
And finally there is the Client class which will use the commands to switch the lights on and off.
//Client public class Client { public static void main(String[] args) { RemoteControl control = new RemoteControl(); Light light = new Light(); Command lightsOn = new LightsOnCommand(light); Command lightsOff = new LightsOffCommand(light); //switch on control.setCommand(lightsOn); control.pressButton(); //switch off control.setCommand(lightsOff); control.pressButton(); } }
Real life applications
The command pattern can be used when the following things are desired:
- Specify,queue and execute requests at different times.
- To support operations like Undo,Redo.
- Support Logging changes so that they can be reapplied in case of a system crash.If the command interface is extended to include the load and store operations, a persistent history of changes can be kept.
- These can also be applied to transactions. They have a common interface so all the transactions can be invoked in the same way. It is also helpful to rollback transaction if something goes wrong.
- It is also used for implementing GUI objects. In addition to the ability to perform the desired command, an Action may have an associated icon, keyboard shortcut, tooltip text, and so on.
For an additional list of applications users can read this [1].
Chain of Responsibility
Chain-of-responsibility pattern is another behavioral design pattern consisting of a source of command objects and a series of processing objects. Processing objects contain logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. The basic intent of this pattern is to chain the receiving objects and pass the request along the chain until an object handles it. This pattern promotes decoupling between senders and receivers by giving multiple objects a chance to handle a request. The request gets passed along a chain of objects until one of them handles it. More information can be handled from here [2].
Example of Chain of Responsibility
The above figure helps to understand the workings of Chain of Responsibility pattern.The example given in [3] has been described below.
//Interface public interface Chain { public abstract void setNext(Chain nextInChain); public abstract void process(Number request); }
//Receiver public class Number { private int number; public Number(int number) { this.number = number; } public int getNumber() { return number; } }
//Concrete Handler1 public class NegativeProcessor implements Chain { private Chain nextInChain; public void setNext(Chain c) { nextInChain = c; } public void process(Number request) { if (request.getNumber() < 0) { System.out.println("NegativeProcessor : " + request.getNumber()); } else { nextInChain.process(request); } } }
//Concrete Handler2 public class ZeroProcessor implements Chain { private Chain nextInChain; public void setNext(Chain c) { nextInChain = c; } public void process(Number request) { if (request.getNumber() == 0) { System.out.println("ZeroProcessor : " + request.getNumber()); } else { nextInChain.process(request); } } }
//Concrete Handler3 public class PositiveProcessor implements Chain { private Chain nextInChain; public void setNext(Chain c) { nextInChain = c; } public void process(Number request) { if (request.getNumber() > 0) { System.out.println("PositiveProcessor : " + request.getNumber()); } else { nextInChain.process(request); } } }
//Client public class TestChain { public static void main(String[] args) { //configure Chain of Responsibility Chain c1 = new NegativeProcessor(); Chain c2 = new ZeroProcessor(); Chain c3 = new PositiveProcessor(); c1.setNext(c2); c2.setNext(c3); //calling chain of responsibility c1.process(new Number(99)); c1.process(new Number(-30)); c1.process(new Number(0)); c1.process(new Number(100)); } }
In the above example the Chain interface is implemented by three handlers which handles 3 different types of numbers-positive numbers,negative numbers and the number zero. The first in the chain is the negative number handler which sets the next handler as the zero handler which in turn sets the positive handler as the last component in the chain.The Number class acts as the receiver which has been explained in the Command pattern.The TestChain is the client.
Comparison with Command Pattern
- Both in Command and Chain of Responsibility pattern commands or actions are stored so that it can be later used.
- The Chain of Responsibility forwards requests along a chain of classes, but the Command pattern forwards a request only to a specific object.
- The main intent of both the patterns is to decouple senders and receivers.In case of Command pattern that is only one.
Real life applications
Chain of Responsibility is used in many applications:
- It is used often to handle exceptions inside kernel.There will be a chain of interrupt handlers and the request is passed on until somebody handles it.
- The pattern is used in windows systems to handle events generated from the keyboard or mouse.
- Single sign on security solutions for web applications. You might have a handler to check if the user is already authenticated, another handler to check for windows authentication, and a last handler to transfer the request to a logon page[4].
Memento
The memento pattern is a software design pattern that facilitates the restoration an object to its previous state. The memento pattern has three different components:[5]
- Originator - the object that has an internal state and knows to save itself.
- Caretaker - the object that knows why and when the Originator needs to save and restore itself.
- Memento - the object (token) that is written and read by the Originator, and taken care by the Caretaker.
The communication between different components in memento pattern happens in the following way: The caretaker first asks the originator for a memento object. Then it does the work it was slated to do. To roll back to the state before the operations, it returns the memento object to the originator. The memento object itself is an opaque object (one which the caretaker cannot change). When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object.In other words, the memento pattern can be viewed as maintaining a "checkpoint" so that the originator can easily rollback to the previous checkpoint.[6]
The following diagram illustrates the memento pattern:
Example of Memento Pattern
The following program illustrates the "undo" usage of the Memento Pattern [7].
import java.util.List; import java.util.ArrayList; class Originator { private String state; // The class could also contain additional data that is not part of the // state saved in the memento. public void set(String state) { System.out.println("Originator: Setting state to " + state); this.state = state; } public Memento saveToMemento() { System.out.println("Originator: Saving to Memento."); return new Memento(state); } public void restoreFromMemento(Memento memento) { state = memento.getSavedState(); System.out.println("Originator: State after restoring from Memento: " + state); } public static class Memento { private final String state; public Memento(String stateToSave) { state = stateToSave; } public String getSavedState() { return state; } } } class Caretaker { public static void main(String[] args) { List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>(); Originator originator = new Originator(); originator.set("State1"); originator.set("State2"); savedStates.add(originator.saveToMemento()); originator.set("State3"); // We can request multiple mementos, and choose which one to roll back to. savedStates.add(originator.saveToMemento()); originator.set("State4"); originator.restoreFromMemento(savedStates.get(1)); } }
The output is:
Originator: Setting state to State1 Originator: Setting state to State2 Originator: Saving to Memento. Originator: Setting state to State3 Originator: Saving to Memento. Originator: Setting state to State4 Originator: State after restoring from Memento: State3
Comparison with Command Pattern
- The similarity between 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 of an object 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.
- Command can use Memento to maintain the state required for an undo operation.
- In practice, the Memento pattern is a little brittle. Changes in the behavior of related objects could lead to changes in what has to be stored. However since command pattern separates out the responsibility for reversibility into the relevant transitions, it proves to be less brittle. Furthermore, command objects can be extended in further directions, taking in permissions, interruptibility, batching, to name but a few.
Real life applications
The following are the applications where memento pattern can be used:
- An interesting game in which memento pattern can be used is Prince of Persia: Sands of Time. In the game, you can hit a button that reverses time. By storing the state of every actor in recent frames, it can just as easily rewind them.
- Another simple application where memento pattern can be used is a calculator that finds the result of addition of two numbers, with the additional option to undo last operation and restore previous result.
- Memento pattern is useful when you need to find the seed of a pseudorandom number generator and the state in a finite state machine.
In all the above applications the "undo" feature is common. Hence, An unlimited “undo” and “redo” capability can be readily implemented with a stack of Command objects and a stack of Memento objects.
Strategy
The unofficially accepted definition for the Strategy Pattern is: "Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it."[8]. In other words, the Strategy Pattern encapsulates a collection of functions that do more or less similar tasks but not identical tasks. Strategy pattern is used when we need to take a decision of which strategy to use based on the input parameters. An important feature of strategy pattern is that client is aware of all the available strategies and which strategy to adopt. It helps is design a system that is elegant, extensible, and powerful.
Example
The following example is in Java.[9]
// The classes that implement a concrete strategy should implement this. // The Context class uses this to call the concrete strategy. interface IStrategy { int execute(int a, int b); } // Implements the algorithm using the strategy interface class ConcreteStrategyAdd implements IStrategy { public int execute(int a, int b) { System.out.println("Called ConcreteStrategyAdd's execute()"); return a + b; // Do an addition with a and b } } class ConcreteStrategySubtract implements IStrategy { public int execute(int a, int b) { System.out.println("Called ConcreteStrategySubtract's execute()"); return a - b; // Do a subtraction with a and b } } class ConcreteStrategyMultiply implements IStrategy { public int execute(int a, int b) { System.out.println("Called ConcreteStrategyMultiply's execute()"); return a * b; // Do a multiplication with a and b } } // Configured with a ConcreteStrategy object and maintains a reference to a Strategy object class Context { private IStrategy strategy; // Constructor public Context(IStrategy strategy) { this.strategy = strategy; } public int executeStrategy(int a, int b) { return strategy.execute(a, b); } } // Test application class StrategyExample { public static void main(String[] args) { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyAdd()); int resultA = context.executeStrategy(3,4); context = new Context(new ConcreteStrategySubtract()); int resultB = context.executeStrategy(3,4); context = new Context(new ConcreteStrategyMultiply()); int resultC = context.executeStrategy(3,4); System.out.println("Result A : " + resultA ); System.out.println("Result B : " + resultB ); System.out.println("Result C : " + resultC ); } }
Comparison with Command Pattern
The difference between Strategy Pattern and Command pattern is in the purpose itself:
- Command encapsulates a single action. It therefore tends to have a single method with a rather generic signature. It often is intended to be stored for a longer time and to be executed later - or it is used to provide undo functionality as explained in the Command pattern section.Strategy, in contrast, is used to customize an algorithm. A strategy might have a number of methods specific to the algorithm. Most often strategies will be instantiated immediately before executing the algorithm, and discarded later.
- Strategies encapsulate algorithms. Commands separate the sender from the receiver of a request, they turn a request into an object. If it's an algorithm, how something will be done, use a Strategy. If you need to separate the call of a method from its execution use a Command.
Real life applications
The applications where strategy pattern is useful are as follows:
- Strategy pattern is used in an system where we try to book the most inexpensive ticket from source to destination. Depending on the users preference of seats, time of transit and other preferences the system chooses the algorithm that will cater to all the user needs at an optimum fare.
- Strategy pattern can be used when we have to sort numbers. Depending on the type of input, we can make use of the best algorithm. For example, if we know that the numbers are almost sorted then we make use of insertion sort. If the numbers to be sorted are within a range, then we make use of counting sort. If the input sequence is random then our best bet is to use merge sort.
- A strategy pattern can be used when we want to read a file that has been transferred over a network. If the file is an XML File then use an XML parsing algorithm. If it is JSON file then use a JSON parser and so on.
Conclusion
Thus, we see that Command Pattern is quite useful. The Chain of Responsibility, Memento ad Strategy pattern adopt the concept of Command patterns and have their own variations which make them useful in different scenarios as mentioned in each of the sections. The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that knows how to perform it. The major disadvantage of the pattern is that it results in many Command classes that can clutter up a design. If the classes are not designed properly it may lead to bloating of the design and will increase the cost of maintaining such a design.