Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt * Object-Oriented Software Development Part 11 Introduction to Design Patterns: Iterators revised March 6, 2002
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 2 Iterating Through A Vector Suppose we want to "step through" a Vector object, retrieving each of the objects stored in the vector, one at a time; for example: import java.util.*; public class IterationExample1 { public static void main(String args[]) { Vector v = new Vector(); // Put some Complex number // objects in the vector. v.addElement(new Complex(3.2, 1.7));
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 3 Iterating Through A Vector v.addElement(new Complex(7.6)); v.addElement(new Complex()); v.addElement(new Complex(-4.9, 8.3)); Complex c; for (int i = 0; i < v.size(); i++) { c = (Complex)v.elementAt(i); System.out.println(c); }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 4 Iterating Through A Vector This approach works well for vectors because the elements of a vector can be retrieved by specifying their position: v.elementAt(i); We start by retrieving element 0, then retrieve element 1, etc., until we retrieve the last element (at position v.size() - 1)
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 5 What About Other Collection Classes? This approach doesn't work well for all collection classes: –what would a position (i.e. index) mean for a Set ? –values stored in a Hashtable object are retrieved by keys, not by position Is it possible to come up with a more general approach, that can be used to iterate over any collection of objects? There must be a general design solution to this…
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 6 Design Patterns "Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice." Christopher Alexander, A Pattern Language: Towns/Buildings/Construction, 1977 A object-oriented design pattern systematically names, explains and evaluates an important and recurring design in object-oriented systems
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 7 Design Patterns The landmark book on software design patterns is: Design Patterns: Elements of Reusable Object-Oriented Software Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides Addison-Wesley, 1995 This is also known as the GOF (“Gang-of-Four”) book.
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 8 Design Patterns Design Patterns follow a certain structure: Name Problem Solution Forces (or Consequences) Additional topics: Implementation Known uses Related Patterns
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 9 Design Pattern Problem: how can I “provide a way to access the elements of an aggregate object (i.e., an object that contains a collection of objects: Vector, Hashtable, LinkedList,...) sequentially without exposing its underlying representation”?
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 10 Iterator Pattern Solution: The responsibility for accessing and traversing an aggregation object is placed in a separate iterator object, not in the aggregation object All iterator objects should provide the same interface for accessing and traversing elements, regardless of the class of the aggregate object and the kind of traversal that is performed
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 11 GOF Iterator Pattern Iterator next() isDone() … ConcreteIterator ConcreteAggregate createIterator() return new ConcreteIterator(this) The arrow represents the association between ConcreteIterator and ConcreteAggregate : a ConcreteIterator object holds a reference to the ConcreteAggregate object that created it. createIterator() Aggregate
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 12 GOF Iterator Pattern Participants: Iterator –defines an interface for accessing and traversing elements ConcreteIterator –implements the Iterator interface. –keeps track of the current position in the traversal of the aggregate Aggregate –defines an interface for creating an Iterator object ConcreteAggregate –creates and returns an instance of the proper ConcreteIterator
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 13 GOF Iterator Pattern Forces / Consequences: “It supports variations in the traversal of an aggregate”: you can use different ways of iterating by defining various concrete subclasses of Iterator for your collection. “Iterators simplify the Aggregate interface” “More than one traversal can be pending on an Aggregate”
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 14 GOF Iterator Pattern Implementation: Good news: there is direct support for the iterator pattern in Java! In the previous slides, the names of the participating classes and the operations they provide were the ones used in the GOF book. As we shall see, the support for the iterator pattern provided in the Java SDK is based on Java interfaces, not abstract classes (why?), and the operations differ slightly from the ones shown in the diagram, but the basic idea is the same.
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 15 Collection Classes & Iterator Objects The Collection interface provides an iterator() method to be implemented by all concrete collections: Iterator iterator() –Collection plays the role of the “Aggregate” in the GoF Iterator pattern A “ConcreteAggregate” (i.e. Vector, LinkedList …) implementing this method should create and return a iterator object
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 16 Iterator Objects An Iterator object mainly provides two methods: –public boolean hasNext() –returns true if the Iterator object has more elements (objects) that have not yet been returned by next() –public Object next() –returns the next element (object) from the iteration
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 17 Iterating Through a Vector // Create a vector object and initialize // it with Complex objects Complex c; Iterator i; i = v.iterator(); while (i.hasNext()) { c = (Complex)i.next(); System.out.println(c); }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 18 Iterating Through Any Collection ex: the code below shows how AbstractCollection implements addAll() without making any assumption on the nature of the collection that is passed as an argument: public boolean addAll(Collection from) { Iterator iter = from.iterator(); boolean modified = false; while (iter.hasNext()) if (add(iter.next())) modified = true; return modified }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 19 Iterating Through a Hashtable Hashtable does not implement Collection, and therefore does not have methods that return Iterator objects for the keys and values in the table Instead: –entrySet() returns a Set of the entries in the table –keySet() returns a Set of the keys in the table –values() returns a Collection of the values in the table iterator() messages are sent to these objects See the Java 1.2 API Specification for more information
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 20 Enumerations The “old” way (before the introduction of the Collection Framework) of stepping through a Vector or a Hashtable was to use Enumeration objects. Enumerations are similar to iterators and provide the two following methods: boolean hasMoreElements() Object next() To get an Enumeration for a Vector, call the elements() method on the Vector object. To get an Enumeration for the keys of a Hashtable, use the keys() method on the Hashtable object. To get an Enumeration for the elements of a Hashtable, use the elements() method on the Hashtable object.
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 21 Building an Iterator Suppose we have a class called CircularList that provides these methods (other CircularList methods not shown here): // Constructor. public CircularList(); // Return the count of the number of // elements in the list. public int count(); // Return the element stored at the specified // position in the CircularList. public Object get(int index); // Remove the element stored at the specified // position in the CircularList. public Object remove(int index);
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 22 Building an Iterator How do we build an iterator (i.e., an Iterator object) for this class? We want an object that lets us do this: CircularList l = new CircularList();... //store integers in the list... Iterator i = l.iterator(); while (i.hasNext()) { System.out.println(i.next()); }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 23 The Iterator Interface When we look through the documentation for the Java API, we discover that Iterator is an interface, not a class: public interface Iterator { public boolean hasNext(); public Object next(); public void remove(); } An Iterator object is an instance of a class that implements the Iterator interface; i.e., defines the hasNext(), next(), and remove() methods
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 24 Class CircularListIterator Iterator objects for class CircularList will be instances of class CircularListIterator: class CircularListIterator implements Iterator { public boolean hasNext() {} public Object next() {} public void remove() {} }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 25 Class ListIterator How can the Iterator object (an instance of CircularListIterator ) access the elements stored in a CircularList object? –the easiest way is for the CircularListIterator object to contain a reference to the CircularList object –it can then send messages to the CircularList object to retrieve the elements
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 26 Class CircularListIterator class CircularListIterator implements Iterator { private CircularList myList; public Object next() {} public boolean hasNext() {} public void remove() {} }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 27 Class CircularListIterator How does a CircularListIterator object obtain the reference to the CircularList object? –pass a reference to the CircularList object to CircularListIterator ’s constructor
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 28 Class CircularListIterator class CircularListIterator implements Iterator { private CircularList myList; public CircularListIterator(CircularList theList) { myList = theList; } public Object next() {} public boolean hasNext() {} public void remove() {} }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 29 Class CircularListIterator How should a CircularListIterator object traverse a CircularList object? Because elements in a list are accessed by position, an easy way is to traverse the list from front to back
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 30 Class CircularListIterator class CircularListIterator implements Iterator { private CircularList myList; // constructor not shown private int pos = 0; public Object next() { Object o = myList.get(pos); // Update pos to indicate the position of // the element that will be returned the // next time this method is invoked. pos++; return o; }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 31 Class CircularListIterator public boolean hasNext() { return(pos < myList.count()); } public void remove() { if (pos > 0) { myList.remove(pos-1); // This method should throw an // IllegalStateException if next() has not // yet been invoked, or if remove() has // already been invoked after the last // invocation of next(). }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 32 Modifying Class CircularList All that remains is to define a method in CircularList to create and return a CircularListIterator object In order to be consistent with other Java collection classes, we'll call the method iterator() class CircularList { public Iterator iterator() { // Create a CircularListIterator object,passing // it a reference to this CircularList object. return new CircularListIterator(this); }
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 33 Interfaces and is-a Relationships Notice that CircularList ’s iterator() returns a reference to a CircularListIterator object, but the method’s return type is Iterator Q: Why is this o.k? A: CircularListIterator implements the Iterator interface –i.e., a CircularListIterator object is-a(n) Iterator object In other words, is-a relationships exist between –a subclass and a superclass –an interface and the class that implements the interface
Copyright © 2002, Systems and Computer Engineering, Carleton University Patterns.ppt 34 CircularList-CircularListIterator Relationships CircularList Iterator The arrow represents the association between CircularListIterator and CircularList : a CircularListIterator object holds a reference to the CircularList object that created it. CircularListIterator implements the Iterator interface