Design patterns II : Behavioural Patterns J.Serrat 102759 Software - - PDF document
Design patterns II : Behavioural Patterns J.Serrat 102759 Software - - PDF document
Design patterns II : Behavioural Patterns J.Serrat 102759 Software Design September 29, 2013 Index Template method 1 Strategy 2 Observer 3 Mediator 4 Visitor 5 State 6 Command 7 Chain of responsibility 8 Iterator 9 Overview
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Overview
Behavioural patterns concern algorithms and the assignment of responsibilities between objects to implement them describe not just structure of classes but also the patterns of communication between them these patterns characterize complex control flow that’s difficult to follow at run-time express complex flow of control through the way objects are interconnected based more on object composition than class inheritance (read this again at the end)
3 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
Motivating example1 You want to program several games like chess, checkers, snakes and ladders, poker . . . They are played differently but have in common : several players, each playing against the others
- nly one is playing at a given time
playing order is : first player, second player . . . last, first, second . . . game starts at an initial state there is some game over condition, a unique winner
1Wikipedia, http://en.wikipedia.org/wiki/Template_method_pattern 4 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
class Monopoly extends Game { void initializeGame() { // Initialize players // Initialize money } void makePlay(int player) { // Process one turn of player } boolean endOfGame() { // Return true if game is over // according to Monopoly rules } void printWinner() { // Display who won } // ... } class Chess extends Game { void initializeGame() { // Initialize players // Put the pieces on the board } void makePlay(int player) { // Process a turn for the player } boolean endOfGame() { // Return true if in Checkmate or // Stalemate has been reached } void printWinner() { // Display the winning player } // ... }
5 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
abstract class Game { protected int playersCount; abstract void initializeGame(); abstract void makePlay(int player); abstract boolean endOfGame(); abstract void printWinner(); /* A template method : */ public final void playOneGame(int playersCount) { this.playersCount = playersCount; initializeGame(); int j = 0; while (!endOfGame()) { makePlay(j); j = (j + 1) % playersCount; } printWinner(); } }
6 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
7 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
Intent Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure. Applicability implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behaviour that can vary factor common behaviour to avoid code duplication define a template method that calls “hook” operations at specific points, thereby permitting extensions only there Hook operations may be overridden, abstract operations must be
- verridden, final operations can not be overridden.
8 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Template method
Structure
9 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Motivating example You are building a text editor application. Text in paragraphs of a composition must be right and left justified so that line breaks seem to be placed at the same column :
10 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
There are at the moment 3 types of line breaking computation algorithms : simple: considers each line at a time TeX algorithm : global optimization of line breaks in a composition Array algorithm : each line has the same number of characters
11 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
First solution Problem : Composition class gets bigger, more complex and harder to maintain, especially if must support multiple linebreaking algorithms
12 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Second solution: inheritance Problems : proliferation of classes, almost identical fixed linebraking algorithm for each composition
13 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Third solution: strategy pattern Which OO principle are we applying ? favor composition over inheritance
14 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Intent Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
Composition introduction = new Composition(new TeXCompositor()); introduction.setText("Thispaperdealswithblablabla"); String composedText = introduction.compose(); // change composition algorithm at run time introduction.setCompositor(new SimpleCompositor()); composedText = introduction.compose();
15 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Structure
16 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Applicability many related classes differ only in their behaviour, each time
- nly one behaviour applies
you need different variants of an algorithm, maybe with different space/time trade-offs an algorithm uses data that clients shouldn’t know about a class defines many behaviours appearing as multiple conditional statements
17 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
class Composition { public static int SimpleStrategy = 1; public static int TeXStrategy = 2; public static int ArrayStrategy = 3; public String compose (int breakingStrategy) { switch (breakingStrategy) { case SimpleStrategy: return composeSimple(text); break; case TeXStrategy: return composeTex(text); break; case ArrayStrategy: return composeArray(text); break; } } private String composeSimple(String str) { // ...
18 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Strategy
Drawbacks Clients must be aware of different strategies. Use the Strategy pattern only when the variation in behaviour is relevant to clients Increased number of objects in an application execution, memory overhead (but see Flyweight pattern)
19 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Motivating example we want to implement a desktop widget representing a clock two types of clocks are possible: digital and analogic digital clock shows time in hh:mm format, analogic in hh:mm:ss there are two responsibilities: storing and updating time, displaying time want to reuse as much as possible of the classes, e.g. to make an alarm application
20 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
ClockTimer is a (or has an object) thread able to periodically : ask system date and call method tick tick invokes update/s and sends it/them the present date update redraws the clock accordingly, if needed but we don’t want class ClockTimer to depend on (know) DigitalClock, AnalogicClock in order to reuse it
21 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
In object oriented designs classes cooperate to achieve functionalities, but tight coupling is not desirable : objects of many classes know/depend/send messages to objects of many other classes. Intent Define a one-to-many dependency between objects so that when
- ne object changes state, all its dependents are notified and
updated automatically. However, the changing object doesn’t know its dependents.
22 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
23 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Observer is implemented in java.util library Observable
knows its observers (any number of objects) provides an interface for adding and removing Observer
- bjects.
Observer
defines an updating interface for objects that should be notified of changes in Observable
Concrete observable Clock
stores state of interest to concrete Observers (present time) sends a notification to its observers when its state changes through notifyObservers
24 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Concrete observers DigitalClock, AnalogicClock
implement the updating interface update may receive the concrete Observable object through update, and/or some other object
// in Clock private void tick() { date = new Date(); setChanged() notifyObservers(this); } // in DigitalClock, AnalogicClock public void update(Observable arg0, Object arg1) { Date presentDate = ((Clock) arg0).getDate(); //... draw(); } // in Clock private void tick() { date = new Date(); setChanged() notifyObservers(date); } // in DigitalClock, AnalogicClock public void update(Observable arg0, Object arg1) { Date presentDate = (Date) arg1; //... draw(); }
25 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Note : need to call setChanged() previous to notifyObservers(),
- therwise nothing happens
need to inherit from Observable, but Java doesn’t feature multiple inheritance can not try composing an Observable because setChanged() is protected inheritance from Observable is not a problem since it’s a Java interface
- ne same class could be observer and observable at the same
time
26 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Structure
In former implementation, a concrete observer does not maintain a reference to a concrete subject/observable
27 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Observer
Applicability an abstraction has two aspects, one dependent on the other, encapsulated in separate objects to vary and reuse them independently a change to one object requires changing others (maybe of different types), and you don’t know how many objects need to be changed an object should be able to notify other objects without making assumptions about who these objects are: you don’t want these objects to be tightly coupled
28 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
LibreOffice dialog Format → Character. . .
29 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
LibreOffice dialog Format → Character. . .
30 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
31 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
public class FontDialog extends org.eclipse.swt.widgets.Dialog { private Combo family; //... public void open() { family = new Combo(dialogShell, SWT.NONE); family.add("TimesRoman"); family.add("Courier"); family.add("Arial"); family.addSelectionListener(new SelectionListener(){ // anonymous class @Override public void widgetSelected(SelectionEvent arg0) { // prints array index of selected item System.out.println( family.getSelectionIndex() ); } }); //...
32 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
Ubuntu Pluma text editor : different dependencies and behaviour
33 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
Motivating example : what’s the problem
- bject-oriented design encourages the distribution of
behaviour among objects (that’s ok) too many connections between objects worst case : every object needs to know about every other less likely that an object can work without the support of
- thers : no chance of reuse
main problem: complex object interactions (the dialog logic) distributed among different classes − → difficult to change
34 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
Solution : encapsulate interactions logic in a separate mediator object mediator knows all objects, collaborating objects only know the mediator mediator is an intermediary responsible for coordinating a group of objects
35 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
36 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
Structure
There’s no need to define an abstract Mediator class when colleagues work with only one mediator. Colleagues have to communicate with their mediator when an event of interest occurs. One approach is using Observer: Colleague is Observable, Mediator Observer
37 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Mediator
Observer versus Mediator O : distributes communication between objects M : encapsulates and centralizes communication O : a single observable usually has many observers, sometimes an object is simultaneously observer and observable Mr : each colleague is related to a unique mediator O : observers and observables are usually connected shortly after created, it’s hard to see how they are connected later M : centralized flow of communication easier to understand
38 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Motivating example : compilers represent source code as “syntax trees”, being nodes variables, expressions, assignments, conditionals, loops . . . then process syntax trees for different purposes: type-checking, optimization, code generation, metrics, instrumentation, pretty printing . . . process means
traverse the tree perform a different operation depending on the node type (an
- f course, process)
39 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Problems: distributing operations of one process across node classes leads to a system that’s hard to understand and change node classes get very large if there are many types of processes mixes in one same class code of very different processes : against OO principle “just one reason to change” adding support for a new process implies changing all node classes We would like node operations to beout of node classes, but can not because they need node data and methods.
40 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Solution : package operations of same process for every node class in a separate object, a visitor add acceptVisitor(Visitor vis) method to each node class pass visitor to node objects as tree is traversed acceptVisitor of node class X calls vis.visitNodeX(this)
41 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Structure
42 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Applicability an structure (list, tree, graph . . . ) contains many classes of
- bjects
want to perform a set of operations on them that depend on their concrete classes do not want to “pollute” classes with these operations want to keep related operations together in one class structure classes rarely change, but will add new operations
43 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Consequences : add a new operation is easy : make a new visitor add a new class X in the structure is difficult: add a new visitX(X) every visitor may combine with Iterator to traverse the structure structure may be a Composite visitor object may accumulate state while traversing (e.g. count number of visited objects of each type) may be forced to break encapsulation of visited classes to allow visitors do their job
44 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Who is responsible for traversing the object structure?
1 the structure object 2 use an iterator (exercise) 3 the visitor itself (exercise) 45 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Collection (like ArrayList)
Collection<Element> elements = new ArrayList<Element>(); Visitor typeChecking = new TypeChecking(); //... for (Element el : elements) { el.acceptVisitor(typeChecking); }
46 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Visitor
Composite (tree, pre-order)
public abstract class Component() { public abstract void acceptVisitor(Visitor vis); } class Leaf extends Component { public void acceptVisitor(Visitor vis) { vis.visitLeaf(this); } } class Composite extends Component { Collection<Component> children = new ArrayList<Component>(); public void acceptVisitor(Visitor vis) { vis.visitComponent(this); for (Component child : children) { child.acceptVisitor(vis); } } }
47 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
Motivating example : model behaviour of players in a maze game
48 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
Motivating example : behaviour of players in a maze game
public class Player { static final int WeakMode = 1; static final int NormalMode = 2; static final int Power = 3; private int mode; private int room; // where’s player //... public void crossDoor(Door door) { if (door.isOpen()) // update player location door.cross(this); else switch mode { WeakMode : // nothing can be done break; NormalMode : // knock and if somebody on the // other side opens it, enter if (door.knock().isOpen()) { door.cross(this); } break; PowerMode : // *can* open doors door.open(); door.cross(this); break; } } public void enterRoom(Room room) { // no door switch mode { WeakMode : //... NormalMode : //... PowerMode : //... } public void crossWall(Wall wall) { // sometimes can be crossed switch mode { WeakMode : //... NormalMode : //... PowerMode : //... } 49 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
Problems : behaviour operations depending on the player’s mode have long and highly redundant conditional structures (switch) adding a new mode implies changing all these operations state transitions have no explicit representation, they only show up as assignments to some variables
50 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
Solution
51 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
places state-specific behaviour in a state subclass, for different states new states and transitions can be added easily by defining new subclasses increases the number of classes, but that’s ok if there are many states (long, redundant conditionals) states are more explicit state transitions logic may be partitioned among the State subclasses if State objects have no context-dependent attributes then contexts can share a State object (Singleton pattern)
52 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
State
Intent Allow an object to alter its behaviour when its internal state
- changes. The object will appear to change its class.
Structure
53 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
Motivating example : micro text editor interface menus
54 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
menuFile = new Menu("File", true); menuItemOpen = new MenuItem("Open..."); menuItemExit = new MenuItem("Exit"); menuFile.add(menuItemOpen); menuFile.add(menuItemExit); menuItemOpen.addActionListener(new FileOpen()); menuItemExit.addActionListener(new FileExit()); //... class FileOpen implements ActionListener { public void actionPerformed(ActionEvent e) { FileDialog fDlg = new FileDialog(frame, "Openafile", FileDialog.LOAD); fDlg.show(); } } class FileExit implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } }
55 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
56 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
The problem : AWT is a Java toolkit to build user interfaces has classes Frame (window), Panel (container of other controls), TextArea (holds text), Menu with options MenuItem MenuItem objects must issue a request to some object in response to user input class MenuItem can not know nothing about the operation being requested or the receiver of the request
- nly the Frame ExampleCommand class knows it, because it
builds the UI from AWT controls
57 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
Solution : the key is the ActionListener interface: it declares the interface actionPerformed(ActionEvent evt) each concrete ActionListener class implements actionPerformed to answer to user input some ActionListener object, the receiver, is associated to each MenuItem by the UI builder, ExempleCommand MenuItem class knows it has to call actionPerformed from its ActionListener when the menu item is selected ActionListener interface is the Command
58 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
Intent Encapsulate a request as an object, thereby letting you parametrize clients with different requests, queue or log requests, and support undoable operations. Structure
59 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
Advantages : decouple the object that invokes the operation from the one having the knowledge to perform it the object that issues a request only needs to know how to issue it, not how the request will be carried out different ways to invoke the same operation: shorcuts Ctrl+S, Save menu item, save button in toolbar. 3 controls/events, a unique action listener it’s easy to add new commands
60 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Command
Advantages : we can define a MacroCommand class to allow a MenuItem to execute a sequence of commands using Composite : can change commands at run-time : context-sensitive menus where one same menu item does different things at different times commands can support undo and redo capabilities if they provide a way to reverse their execution
61 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
Motivation example: an airplane has a number of compartments : baggage and animals cargos, pilot cabin, passenger space, toilets . . . each compartment has one or more sensors each sensor is actually a box with 4 sensors: temperature, pressure, O2 level, CO2 level sensors send signals to controllers, which may send alerts and
- ptionally regulate other devices
62 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
Motivation example: each compartment has a cabin controller that
seals doors and sends alert if pressure level drops regulates air conditioning fans sends alert if temperature rises above threshold
a central O2 controller that
regulates O2 mix in air controls O2 tanks sends alert if level drops blow threshold
a master controller receives and logs alerts, and shows them in pilot panel
63 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
sensor cabin controller cabin controller O2 controller master controller sensor
64 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
We want sensors to send requests to controllers a controller can handle completely the request (e.g. cabin controller decrease speed of air conditioning fan) alert requests can not be handled by cabin controller but needs to arrive to other controller/s do not want to attach every sensor to its cabin and the O2 and the master controllers Solution : chain controllers in a sequence a sensor issues a request to the attached controller if a controller can not handle a request, pass it to next controller define a common interface for controllers
65 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
sensor cabin controller sensor sensor cabin controller sensor O2 controller master controller
66 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
67 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
public Client() { // create controllers tree Controller master = new MasterController(null); Controller O2 = new O2Controller(master); Controller pilotCabin = new CabinController(O2); Controller passengerSpace = new CabinController(O2); Controller toilet = new CabinController(O2); Controller cargo = new CabinController(O2); // attach sensors to controllers Sensor s1 = new Sensor(cargo); Sensor s2 = new Sensor(cargo); Sensor s3 = new Sensor(toilet); //... public class Sensor { public void sendRequest() { controller.handleRequest(Request.Analyze, sensorData); } //...
68 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
public abstract class Controller { public abstract void handleRequest(int req, SensorData sd); public Controller(Controller succ) { successor = succ;} //... public class CabinController extends Controller { public void handleRequest(int request, SensorData sd) { if (request == Request.Analyze) { if (sd.getPressure()<0.5*minPressure) { sealCabinDoors(); successor.handleRequest(Request.Alert,sd); } if (sd.getTemperature()>1.5*maxTemperature) successor.handleRequest(Request.Alert,sd); regulateAirConditionerFan(sd.getTemperature()); } if (request == Request.Record) // pass to next successor.handleRequest(request,sd); //...
69 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
public class O2Controller extends Controller { public void handleRequest(int request, SensorData sd) { if (request == Request.Alert) // pass to next successor.handleRequest(request, sd); if (request == Request.Record) // pass to next successor.handleRequest(request,sd); if (sd.getO2level()<0.75*this.minO2Level) { dropAirMasks(); successor.handleRequest(Request.Alert, sd); } //... public class MasterController extends Controller { public void handleRequest(int request, SensorData sd) { if (request==Request.Alert) { // show alert in pilot panel } if (request == Request.Record) { // save it } //...
70 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
Intent Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it [completely]. Structure
71 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Chain of responsibility
Consequences reduced coupling :
frees an object from knowing which other object handles a request, only has to know how to issue a request an object in the chain doesn’t have to know about the chain’s structure
flexibility : can add or change responsibilities for handling a request by adding to or changing the chain at run-time there’s no guarantee a request will be handled receivers can form a tree with Composite requests can be represented as objects from a Request class
72 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
Motivating example iterating over a data structure is fundamental in many algorithms: traversing lists, trees, graphs . . . these structures are of different subtypes: linked lists, binary and n-ary trees, directed and undirected graphs . . . traversal of these structures normally depends on its internal representation − → also the algorithm we would like to access the elements of an aggregate structure in a certain order (first to last, last to first, randomly, pre-order, post-order) without exposing its underlying representation example: traverse a tree in pre-order without accessing to the nodes child’s list, just asking for the next node until there are no further nodes we do not want to depend on the exact container type (e.g. LinkedList, ArrayList)
73 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
This is what Java iterators do with collections
74 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
public class Person { String name; int age; public Person(String str, int a) { name = str; age = a; } @Override public String toString() { return name + "," + age; } } Person pere = new Person("PereGrau", 36); Person ana = new Person("AnaDeumal", 21); Person genis = new Person("GenisRoig", 19); List<Person> friends1 = new ArrayList<Person>(); friends1.add(pere); friends1.add(ana); friends1.add(genis); HashMap friends2 = new HashMap<Integer, Person>(); friends2.put(30, pere); friends2.put(20, ana); friends2.put(10, genis);
75 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
public void print(Iterator<Person> it) { while (it.hasNext()) { System.out.println(it.next()); } } print(friends1.iterator()); print(friends2.entrySet().iterator()); Pere Grau, 36 Ana Deumal, 21 Genis Roig, 19 10=Genis Roig, 19 20=Ana Deumal, 21 30=Pere Grau, 36
76 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
Solution the aggregate class provides an iterator object − → derived from an abstract class like Container getting an iterator also places it to first element there are several iterator subclasses, one per each aggregate class Iterator is an interface defining at least methods
hasNext() tests whether we have advanced beyond last element next() advances one element
implementations may have others like hasPrevious(), previous(), add(), remove() . . .
77 / 81 Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
Structure
78 / 81
Overview Template method Strategy Observer Mediator Visitor State Command Chain of responsibility Iterator
Iterator
aggregates may be traversed in many ways, just replacing one iterator with a different one iterators simplify the aggregate interface more than one traversal can be done simultaneously on an aggregate, each iterator keeping track of its own traversal state
79 / 81 You should know. . . You should know. . .
You should know
what’s the intent of each behavioural pattern and how does it achieve it motivating example for each pattern implementation of Observer in the java.util API
- ppositeness of Observer and Mediator
recognize Command in listeners of UI toolkits meaning of Iterator Java class frequent combinations: Visitor + Chain of responsibility, Command + Composite, State + Singleton, Singleton + Factory method and Composite . . .
80 / 81
You should know. . . You should know. . .
You should know
what each pattern encapsulates Pattern Aspects that vary Template method The steps of an algorithm Strategy An algorithm Observer Number of objects that depend on another object. How the dependent objects stay up to date Mediator The interaction protocol between objects Visitor
- perations that can be applied to
- bject(s) without changing their class(es)
State A state-dependent behaviour Command When and how a request is fulfilled Chain of responsibility Object that can fulfil a request Iterator The way you access and traverse an aggregate
81 / 81