Week 12
Week 12
EL
PT
N
1
Decorator Pattern: Introduction
• Intent:
– Attach additional responsibilities to objects dynamically.
– Provides a flexible alternative to subclassing.
EL
• A wrapper pattern!
PT
• Motivation:
– Add responsibilities to individual objects as and when
N
required and not to an entire class
– Should conform to the interface of the object.
2
Decorator: In Simple Words
• You have an object:
– You wrap it with another object. Obj
– They both support the same interface.
EL
– Later possibly wrap it with more objects..
PT
– The ones on outside are "decorators"
• A Client uses the outermost decorator.
N
– A decorator passes on a method call to the object
inside it, either as it is or with some enhancement.
3
EL
PT
You were working with a
directory listing window…
N then you decided to resize
it…
4
• A scroll bar has
appeared!!!
EL
PT
N
5
Non-software example
• Suppose you buy a gift:
– First you select the gift…
EL
– Next you ask to wrap the gift
appropriately…
PT
• A gift can be wrapped in several
ways…
N
6
They could provide various options for wrapping gift: Giftwrap
• box wrapped with gift-paper Gift Paper Possibilities
• box wrapped with gift-paper-with-crepe-paper
• box wrapped with gift-paper-with-bow-without-crepe-paper
• box wrapped with gift-paper-with-bow and crepe-paper
Crepe with
Paperbow andBow Card
EL
• box wrapped with gift-paper crepe-paper and
card
• box wrapped with gift-paper with bow and crepe-paper
PT
without card Bow Card Card
• box wrapped with gift-paper without bow with crepe-paper
and card
•
without card Card N
box wrapped with gift-paper without bow with crepe-paper
• Etc…
7
• In order to circumvent the problem, Solution
manufacturers sell the following materials:
–Boxes You can select the ones you
EL
–Gift Paper need and the order you want…
PT
–Cards
–Bows
–Crepe-paper
N
8
Decorator Pattern: Some Examples…
Here, you can add capability to the basic stream class
EL
• Add functionality to an input/output stream :
PT
– Such as reading inputs line by line or compressing
N
a file before sending it over.
9
Decorator: General Concepts
• A Decorator adds responsibilities to individual
objects (not to all objects of a class!) dynamically: Run time
– In situations where a large number of independent
EL
extensions required…
PT
– An explosion of subclasses would occur if every
combination to be supported.
N
– Difficult to understand, remember and apply…
10
Decorator: Review of the main Ideas
• A Decorator is an object that has an interface Obj
identical to an object that it contains.
EL
– Used for adding additional functionality to a particular
object at run time as opposed to a class of objects.
PT
– Any call that a decorator gets, it relays to the object
N
that it contains, and adds its own functionality along
the way, either before or after the call.
11
• The Decorator pattern gives the designer flexibility: Decorator:
– Can change decorator at runtime, as opposed to a static change
Some
determined at compile time by subclassing.
Comments
• Since a Decorator has the same interface as the object it
EL
contains:
– The Decorator is indistinguishable from the object that it contains and
PT
from any other concrete instances, including other decorated objects.
• This is a powerful technique and used to great advantage:
N
– Designers can recursively nest decorators without any other objects
being able to tell the difference, allowing significant customization.
12
Client component 1
interface
Decorator
operation()
Structure
EL
Concrete decorator
component operation()
operation()
PT
N Concrete
decoratorA
Concrete
decoratorB
operation() operation()
13
• Consider a TextView GUI component: An Example
– You want to add different kinds of borders and/or Application
scrollbars to it.
• You can add 3 types of borders:
EL
– Plain, 3D, or Fancy
PT
• and , 1, or 2 two scrollbars
– Horizontal or Vertical
N
• An inheritance solution would require 15 classes.
14
1.TextView_Plain
2.TextView_Fancy Rather
3.TextView_3D Large Number
4.TextView_Horizontal of classes!
5.TextView_Vertical
6.TextView_Horizontal_Vertical
EL
7.TextView_Plain_Horizontal
8.TextView_Plain_Vertical
9.TextView_Plain_Horizontal_Vertical
PT
10.TextView_3D_Horizontal
11.TextView_3D_Vertical
12.TextView_3D_Horizontal_Vertical
N
13.TextView_Fancy_Horizontal
14.TextView_Fancy_Vertical
15.TextView_Fancy_Horizontal_Vertical
15
• The component is contained in another Simpler
object (decorator) that adds the border. Solution
• The decorator conforms to the interface of the component:
EL
–So its presence is transparent to clients
PT
• The decorator forwards requests to the component:
N
–May perform additional actions before or after
forwarding.
16
VisualComponent
draw() 1 Decorator
resize() contains a
visual
component
TextView SteamedVideoView Decorator 1
draw() draw() draw()
EL
resize() resize() resize()
PT
An imagined
example Border ScrollBar
draw() draw()
N resize() resize()
EL
implement the same interface. As a
Concrete decorator
result, they share the same methods,
such as "operation." This similarity
component operation()
allows the client to interact with both the
concrete component and the decorator
operation()
PT
seamlessly, without distinguishing
between them. When decorators are
added, they seamlessly augment the
behavior of the concrete component,
and the client remains unaware of any
N Concrete
decoratorA
Concrete
decoratorB
differences in behavior.
operation() operation()
18
• Consequences: Decorator:
Some Issues
+ Responsibilities can be added/removed at run-time
+ Avoids subclass explosion
+ Recursive nesting allows multiple responsibilities
EL
• Implementation Issues:
PT
– Interface conformance
– Should use a lightweight class as a Decorator
N
– Heavyweight classes make Strategy more attractive
19
• Normal Java GUI components don't have scroll bars Decorator
• JScrollPane is a container with scroll bars to which you example: GUI
can add any component to make it scrollable
EL
JTextArea area = new JTextArea(20, 30);
PT
JScrollPane scrollPane =
new JScrollPane(area); N
contentPane.add(scrollPane);
20
Java Borders
• Any JComponent can have 1 or more borders
• Borders are useful objects that, while not themselves
components:
EL
– Know how to draw the edges of Java Swing components
• Borders are useful not only for drawing lines and fancy
PT
edges:
N
– But also for providing titles and empty space around
components and also some basic behavior.
21
•We have a text object Decorator:
Border Programming
decorator
and … Example
Scrollbar
decorator We want to add a
EL
Original text
object
border
PT
At times we also
want to add a
N scrollbar…
22
Decorator Terminology
Border Scrollbar text
decorators decorated
EL
•The objects refer each other like a linked list or
PT
chain of objects.
N
•The last in the list is the decorated object.
23
• Suppose you have designed a user interface toolkit and you wish Widget and
to provide a choice of border or scrolling. Stream
• Widget aWidget = new BorderDecorator(new Examples
ScrollDecorator(new TextView()));
aWidget.draw();
EL
• Stream Example: Draw class diagram…
PT
–cascade responsibilities to an output stream
Stream aStream = new CompressingStream(
N
new ASCII7Stream(new FileStream( "fileName.dat" )));
aStream.putString( "Hello world" );
24
VisualComponent Decorator
Draw() Example
Solution
TextView Decorator
EL
Draw() Draw()
PT
ScrollDecorator BorderDecorator
Draw()
ScrollTo()N
ScrollPosition
Draw()
DrawBorder()
BorderWidth
25
Disadvantages of Inheritance
• Use of inheritance leads to an explosion of classes
• With another type of border added:
EL
–Many more classes would be needed
–If another view were added such as
PT
StreamedVideoView:
N
–It would double the number of Borders/Scrollbar classes
• Use the Decorator Pattern instead!
26
Decorator: Some Disadvantages
• When tempted to add many decorators:
– A package may become hard to understand…
EL
– Like Java I/O streams!!!
PT
• Solutions become complex:
N
– A factory class may help
27
• An ice cream can be made with the following Quiz
types of toppings in any combination and order:
– Nutty • Apply decorator pattern
Honey • Draw class diagram
EL
–
• Write Java code
– Fruity
PT
– Chocolate
– Vanilla
N
1. Draw class diagram
2. Write Java Code
28
Quiz: Solution
<<interface>>
Icecream
+makeIcecream()
EL
SimpleIcecream IcecreamDecorator
-icecream Icecream
+makeIcecream() Abstract class
PT
+makeIcecream()
concrete classes
+makeIcecream()
-addNuts()
N +makeIcecream()
-addHoney()
+makeIcecream()
-addFruit()
29
Quiz: Java Code public class SimpleIcecream implements Icecream
{
public interface Icecream { public String makeIcecream() {
public String makeIcecream(); return "Base Icecream";
} }
EL
abstract class IcecreamDecorator implements Icecream {
protected Icecream specialIcecream;
public IcecreamDecorator(Icecream specialIcecream) {
PT
this.specialIcecream = specialIcecream;}
public String makeIcecream() {
}
N
return specialIcecream.makeIcecream();}
30
public class NuttyDecorator extends IcecreamDecorator {
public NuttyDecorator(Icecream specialIcecream) {
super(specialIcecream); }
public String makeIcecream() {
return specialIcecream.makeIcecream() + addNuts(); }
private String addNuts() {
EL
return " + cruncy nuts“;}
}
public class HoneyDecorator extends IcecreamDecorator {
PT
public HoneyDecorator(Icecream specialIcecream) {
super(specialIcecream); }
public String makeIcecream() {
N
return specialIcecream.makeIcecream() + addHoney(); }
private String addHoney() {
return " + sweet honey";}
}
31
• More flexible than static inheritance: Decorator: Pros
– Responsibilities can be added and removed at run-time
– Decorators also make it easy to add a property twice. For
example, to give a TextView a double border, simply
EL
attach two BorderDecorators. Inheriting from a Border
class twice is error.
PT
• Avoids inheriting from feature-laden classes.
– An application needn't pay for features it doesn't use.
N
– It's also easy to define new kinds of Decorators
independently from the classes of objects they extend.
32
Decorator: Cons
• Lots of little objects:
– The objects differ only in the way they are
interconnected, not in their class or in the
EL
value of their variables.
PT
– Although these are easy to customize by
those who understand them, they can be
N
hard to learn and debug.
33
• Both are ways to re-use functionality Composition
• Inheritance: vs.
– Re-use functionality of parent class Inheritance
– Statically decided
EL
– Weakens encapsulation
• Composition:
PT
– Re-use functionality of objects at run-time
– Invoked through the interface
–
– Black-box re-use
N
Dynamic: multiple types with same interface
34
• Inheritance is a quick way to design new components: Composition
– That are variants of existing ones vs.
inheritance
• Over-use of inheritance creates bloated hierarchies
– Code is more difficult to maintain
EL
– Unnecessary baggage for many classes
PT
• Composition drawback: it is harder to understand the
behavior of a program by looking only at its source code
N
– Semantics of interaction are decided at run-time
35
Iterator Pattern
EL
PT
N
36
Background
• Traversing through elements in an aggregation is a
very common problem in programming:
– Iterators provide a uniform way of doing this …
EL
• Using an iterator, we don’t need to know:
PT
– How the collection is implemented!
N
– Concurrent access and synchronization are supported
– Other class methods may be accessing the iterator
37
Iterator Pattern: Intent
• Provide a way to access the elements of an
aggregate object sequentially:
– Without exposing the programmer to the
EL
complexity of underlying representation.
PT
• Move the responsibility for access and traversal:
N
– From the aggregate object to an iterator
object.
38
Iterator Pattern
• Helps access an aggregate's contents sequentially:
EL
• Supports the same interface for all aggregates.
PT
• Supports multiple types of traversals of aggregates
N
• Supports multiple iterators
39
Iterator: Essential Idea
• The elements of a collection:
– Accessed in some sequential order that may
be independent of the specific collection.
EL
• For example:
PT
– Level order: Labelling each object of a tree from
left to right N
– Inorder, post order, preorder, etc
40
The Iterator Pattern: Context
• It might be necessary to have more than one type
of traversal on the same aggregate object.
EL
– Also, not all types of traversals can be anticipated a
priori.
PT
• One should not bloat the interface of the
N
aggregate object with all possible traversals.
41
Iterator: Basic Methods
• reset:
– Move to the beginning of the range of elements
EL
• next:
– Returns the next element.
PT
• hasNext:
N
– Interrogate it to see if it is at the end of the range
42
Additional Methods
• remove: Current element is removed, as in Java List.
EL
• count: Return the number of elements
PT
in the aggregate.
• first: Reset
N
43
Iterator Object Methods
• Two methods most common:
– public boolean hasNext()
EL
• Returns true if the aggregate has more elements
(objects) that have not yet been returned by next()
PT
– public Object next()
N
• Returns the next element (object).
44
next() in Java: Some Issues
• Theoretically, when an iterator returns an element of the
collection:
– It might return a clone of the element, or it might return a reference to
EL
the element
PT
– Actually return references
N
• Therefore, modifying the returned value will
modify the element in the collection
45
Iterator Pattern: Main Idea
List ListIterator
EL
count()
append(Element) first()
PT
remove(Element) next()
ListIterator() hasNext()
N
…
46
• The responsibility for accessing and traversing an Iterator
aggregation object: Pattern:
– Placed in a separate iterator object and not in the
Solution
aggregate object
EL
• An iterator object should:
PT
– Provide the same interface for accessing and traversing
N
elements, regardless of the class of the aggregate object
and the kind of traversal performed…
47
Structure of Iterator Pattern
Aggregate A ConcreteIterator
Iterator
object holds a
createIterator()
first() reference to the
next()
EL
ConcreteAggregate
hasNext() object that
created it.
PT
ConcreteAggregate
createIterator() ConcreteIterator
N
return new ConcreteIterator()
48
• Iterator Iterator Participants
– Defines an interface for accessing and traversing elements
• ConcreteIterator
– Implements the Iterator interface.
EL
– Keeps track of the current position in traversal of the aggregate
PT
• Aggregate
– Defines an interface for creating an Iterator object
• ConcreteAggregate N
– Creates and returns an instance of ConcreteIterator
49
Iterator
{abstract} Iterator:
first() : Item Example 1
next() : Item
moreElements() : Bool
EL
ArrayIterator LinkedListIterator
first() : Item first() : Item
PT
next() : Item next() : Item
moreElements() : Bool moreElements() : Bool
Item
NArray LinkedList
*
*
50
public class ArrayIterator public String first() {
index = 0;
Iterator:
implements Iterator {
return data[0];
Example 2
private String[] data;
}
private int index; public String next() {
EL
public ArrayIterator return data[index++];
(String[] data) { }
PT
this.data = data; public boolean moreElements() {
if (index >= data.length)
this.index = 0;
return false;
} N }
return true;
51
public class LinkedListIterator public String first() { Iterator:
implements Iterator { return first.value(); Example 1
private LinkedListElement }
first; public String next() {
private LinkedListElement current = current.getNext();
EL
current; return current.value();
public LinkedListIterator }
PT
(LinkedListElement first){ public boolean moreElements() {
if (current.getNext() == null)
this.first = first;
N
this.current = first;
return false;
return true;
} }
}
52
Iterating Through A Vector: without Iterator
import java.util.*;
EL
public static void main(String args[]) {
PT
Vector v = new Vector();
N
// Put some Complex number objects in the vector.
53
Iterating Through A Vector
v.addElement(new Complex(7.6));
v.addElement(new Complex());
v.addElement(new Complex(-4.9, 8.3));
EL
for (int i = 0; i < v.size(); i++) {
PT
Complex c = (Complex)v.elementAt(i);
System.out.println(c);}
} N
}
54
Iterating Through A Vector Without Iterator
• For vectors this approach does not
appear too bad:
EL
– Because the elements of a vector can be
PT
retrieved by specifying their position:
v.elementAt(i);
N
55
Iterating Through a Vector: Using Iterator
Iterator i = v.iterator();
while (i.hasNext()) {
EL
Complex c= (Complex)i.next();
PT
System.out.println(c);
} N
56
Iterator Iterator for
Collection Java
iterator()
hasNext() Collection
next() Class
EL
ConcreteCollection ConcreteIterator
PT
<<create>> hasNext()
iterator()
next()
N
return new ConcreteIterator()
57
• Support for the iterator pattern provided in Iterator
the Java SDK is based on Java interfaces: Pattern
–Not abstract classes (why?)
in Java
EL
public interface Iterator {
public boolean hasNext();
PT
public Object next();
}
N
public void remove();
58
Java Iterator
• An Iterator object is an instance of a class
that implements the Iterator interface:
EL
– Java Iterator interface defines the
PT
hasNext(), next(), and remove() methods
N
59
Java Collections
Collection Map
EL
Set List
SortedMap
PT
SortedSet Hashtable
N
• Hashtable is an old (pre-Collections) class
• Hashtable has been retrofitted to implement the Map interface
«interface» «interface»
Collection Map
EL
PT
HashSet «interface» Vector ArrayList LinkedList TreeMap HashMap
SortedSet
Linked
HashSet
TreeSet
N
61
• Hashtable does not implement Collection: Iterating
– Therefore does not have methods that return Through a
Iterator objects for the keys and values in the table
Hashtable
• Instead:
EL
– entrySet() returns a Set of the entries in the table
– keySet() returns a Set of the keys in the table
PT
– values() returns a Collection of the values in the table
N
• iterator() messages are sent to these objects
• See the Java 1.2 API Specification for more information
62
Java Iterator public interface java.util.Iterator {
public boolean hasNext();
public interface java.util.Collection { public Object next();
... // List, Set extend Collection public void remove();
public Iterator iterator(); }
EL
}
public interface java.util.Map {
PT
...
public Set keySet();
}
N
public Collection values();
63
Iterators in Java
• All Java collections have a method iterator that returns an
iterator for the collection…
List list = new ArrayList();
EL
... add some elements ...
PT
for (Iterator itr = list.iterator(); itr.hasNext()) {
BankAccount ba = (BankAccount)itr.next();
N
System.out.println(ba);
}
64
• When implementing your own collections, it can Adding
be very convenient to use Iterators your own
– discouraged (has nonstandard interface): Iterators
public class PlayerList {
public int getNumPlayers() { ... }
EL
public boolean empty() { ... }
public Player getPlayer(int n) { ... }
}
PT
– preferred:
public class PlayerList {
N
public Iterator iterator() { ... }
public int size() { ... }
public boolean isEmpty() { ... }
}
65
Implementing an Iterator
• Three main approaches to create an
Iterator for an aggregate class A:
EL
– Use a separate class
PT
– Use an inner class within A
N
– Use an anonymous inner class within A
66
Exercise:
public CircularList(); //constructor Special Iterator
// Count of number of elements in the list.
for CircularList
public int count();
EL
// Return the element stored at the specified position in the CircularList.
PT
public Object get(int index);
// Remove the element stored at the specified position in the CircularList.
N
public Object remove(int index);
67
CircularList l = new CircularList(); Exercise: Build
... an Iterator as a
Separate Class…
//store integers in the list
...
EL
Iterator i = l.iterator();
PT
while (i.hasNext()) {
System.out.println(i.next());
N
}
68
Class Diagram: CircularList Iterator
CircularListIterator
implements the
Iterator Iterator interface
EL
CircularList CircularList
PT
Iterator
N
A CircularListIterator object holds a reference to
the CircularList object that created it.
69
List Iterator Solution:
Create() First() Class
Next() Structure
IsDone()
CurrentItem()
EL
CircularList
PT
Create() ConcreteIterator
N
A ConcreteIterator object holds a reference to the
CircularList object that created it.
70
class CircularListIterator implements Iterator {
EL
public Object next() {}
PT
public void remove() {}
} N
71
Class CircularListIterator: Code Details
class CircularListIterator implements Iterator{
private CircularList myList;
public CircularListIterator(CircularList theList) {
EL
myList = theList; }
PT
public Object next() {}
public boolean hasNext() {}
N
public void remove() {}
}
72
class CircularListIterator implements Iterator {
private CircularList myList;
// constructor not shown Class
private int pos = 0; CircularListIterator
EL
public Object next() {
Object o = myList.get(pos);
PT
pos++;
return o;
} N
}
73
Class CircularListIterator
public boolean hasNext() {
return(pos < myList.count()); }
EL
if (pos > 0) {
myList.remove(pos-1);
PT
// This method should throw an
// IllegalStateException if next() has not
// yet been invoked, or if remove() has
N
// already been invoked after the last
// invocation of next().
}
74
Modifying Class CircularList
• All that remains now:
–Define a method in CircularList to create and return a
EL
CircularListIterator object
PT
• In order to be consistent with other Java
collection classes:
N
–We'll call the method iterator()
75
Modifying Class CircularList
class CircularList{
… … …
EL
public Iterator iterator() {
return new CircularListIterator(this);
PT
}
} N
76
Inner Iterator Class
• Java allows one class to be nested inside
another
EL
• Inner class has full access to private data of
PT
main class
N
– data is still kept as a private field
77
class LinkedList { public Iterator iterator() {
private Node head;
return new LLIterator();
// put all the usual stuff here
}
public class LLIterator implements }
EL
Iterator {
private Node nextObject;
public LLIterator() {
PT
nextObject = head;
}
}
N
78
Interface Polymorphism
• Notice that CircularList’s iterator() returns a reference to a
CircularListIterator object: class CircularList{
public Iterator iterator() {
– but the method’s return type is Iterator return new CircularListIterator(this);
}
EL
– Q: Why is this o.k? }
• Ans: CircularListIterator implements the Iterator interface
PT
– i.e., a CircularListIterator object is-a(n) Iterator object
• In other words, is-a relationships exist between
N
– a subclass and a superclass
– an interface and the class that implements the interface
79
Exercise: Polymorphic Iterators
• Assume that we have an AbstractList class.
• Based on this, we have defineds List and
EL
SkipList subclasses.
PT
• Design Iterators for these different
N
implementations of the AbstractList.
80
AbstractList Client Iterator
CreatIterator() First()
Count() Next()
Append(Item) IsDone()
Remove(Item) CurrentItem()
…
EL
PT
List ListIterator
SkipList
N SkipListIterator
81
List list = new List(); public void handleList(Iterator
SkipList skipList = new iterator) {
SkipList(); iterator.First();
Iterator listIterator = while (!iterator.IsDone()) {
EL
list.CreateIterator(); Object item =
Iterator skipListIterator = iterator.CurrentItem();
PT
skipList.CreateIterator(); // Code here to process item.
handleList(listIterator); iterator.Next();
N
handleList(skipListIterator);
}
}
82
A Few Issues
• Who controls the iteration, e.g. while searching an
item?
• External:
EL
– User explicitly calls all necessary operations.
PT
• Internal:
– Client asks the internal iterator an operation
N
to perform, and the iterator applies that
operation to every element.
83
Pattern Variations
• Who defines the traversal algorithm?
– The iterator is not the only place where the traversal
algorithm can be defined.
EL
– The aggregate might define the traversal algorithm and use
the iterator to store just the state of the iteration.
PT
– This is called the cursor approach
84
Multiple Traversal Algorithms
• Complex aggregates may be traversed in many ways.
• For example, code generation and semantic checking
EL
involve traversing parse trees.
PT
preorder.
N
• Iterators make it easy to change the traversal algorithm:
Just replace the iterator instance with a different one
85
Traversal Issues (cont)
• If the iterator is responsible for the traversal algorithm:
– It becomes easy to use different iteration algorithms on the
same aggregate
EL
– It is easy to reuse the same algorithm on different aggregates.
PT
• But, the traversal algorithm might need to access
private data of the aggregate.:
N
– Putting the traversal algorithm in the iterator
violates the encapsulation of the aggregate.
86
Implementation Issues
• How robust is the iterator?
– If elements are added or deleted, it can become dangerous
to modify an aggregate while you're traversing it.
EL
– Why not just make a copy?
PT
– A robust iterator ensures that insertions and removals
won't interfere with traversal, and it does it without
N
copying the aggregate.
87
Implementation Issues
• There are many ways to implement robust iterators.
– Most rely on registering the iterator with the
aggregate.
EL
• On insertion or removal:
PT
– The aggregate either adjusts the internal state of
iterators it has produced,
N
– Or it maintains information internally to ensure proper
traversal.
88
Iterator: Final Analysis
• Programmer gets a consistent interface to
traverse any collection
EL
• It is easy to have multiple iterators traversing
PT
the same collection
N
• Flexibility: An iterator can give access to a
filtered view of the items in a collection
89