0% found this document useful (0 votes)
53 views10 pages

It Era Tor

The iterator pattern provides a way to access the elements of a collection sequentially without exposing its underlying representation. It allows traversing collection elements through a common interface, supporting multiple traversals concurrently. The pattern defines an iterator interface containing methods like next() and hasNext(), and concrete iterator classes implement this interface to iterate over specific collection types. This allows modification of a collection without affecting code outside the collection and enables polymorphic iteration over different collection structures.

Uploaded by

kashifmirza7
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
53 views10 pages

It Era Tor

The iterator pattern provides a way to access the elements of a collection sequentially without exposing its underlying representation. It allows traversing collection elements through a common interface, supporting multiple traversals concurrently. The pattern defines an iterator interface containing methods like next() and hasNext(), and concrete iterator classes implement this interface to iterate over specific collection types. This allows modification of a collection without affecting code outside the collection and enables polymorphic iteration over different collection structures.

Uploaded by

kashifmirza7
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 10

Behavioral Patterns - Iterator Pattern

What is Iterator Pattern?

Provide a way to access the elements of the aggregate object sequentially without exposing its underlying
representation. Aggregate object is an object that contains other objects for the purpose of grouping those
objects as a unit.It is also called a container or a collection.Examples are linkedList,Hashtable,ArrayList
etc.

Motivation

• Aggregate object such as a list should allow a way to traverse its elements without exposing its
internal structure.
• It should allow different traversal methods.
• It should allow multiple traversals to be in progress concurrently.
• But we really donot want to add all these methods to the interface for the aggregate.

Use of Iterator Pattern

• To Support traversals of aggregate objects without exposing their internal representation.


• To support multiple,concurrent traversals of aggregate objects.
• To provide a uniform interface for traversing different aggregate structures (that is, to support
polymorphic iteration)

Benefits and Drawbacks


Many of the Iterator pattern’s benefits stem from the advantages of defining a uniform interface for
collection
traversal. This greatly simplifies the use of collections, and allows you to use polymorphism when working
with
collections. To print the elements in any collection, for instance, you could obtain an Iterator, then call the
toString method on any object, regardless of its underlying collection.
Additionally, Iterators allow clients to keep multiple navigation points to the same collection. You can think
of an
Iterator as a cursor or pointer into the collection; with each call to the Aggregate’s factory method, you
can get
another pointer into the collection.
A drawback of iterators is that they give the illusion of order to unordered structures. For example, a set
does not
support ordering, and its Iterator would likely provide the elements in an arbitrary sequence that could
change
over time. If you don’t realize this, you could write code that assumed consistency in the underlying
structure,
which would result in problems later on

The Iterator pattern is one, which allows you to navigate through a collection of data using a common
interface without knowing about the underlying implementation.

Iterator should be implemented as an interface. This allows the user to implement it anyway its easier for
him/her to return data.

We use iterators quite frequently in everyday life. For example, remote control of TV. Any remote control
we use, either at home/hotel or at a friend’s place, we just pick up the TV remote control and start
pressing Up and Down or Forward and Back keys to iterate through the channels.

What sort of interface can Iterator be in case of Remote Controls?


/**
* Iterator interface has method declarations for iterating through
* TV channels. All remote controls implement Iterator.
*/
public interface Iterator {

1
public Channel nextChannel(int currentChannel);
public Channel prevChannel(int currentChannel);
}// End of interface

The channel iterator is common for all the remote controls. It’s like a specification implemented by all the
remote control manufacturing companies.

/**
* ChannelSurfer is a part of remote control which implements the Iterator
* interface. This class overrides the nextChannel and prevChannel methods.
*/

public ChannelSurfer implements Iterator {


/**
* nextChannel – method which takes the current channel number
* and returns the next channel.
*/
public Channel nextChannel (int currentChannel) {
Channel channel = new Channel(currentChannel+1);
return channel;
}
/**
* prevChannel – method which takes the current channel number
* and returns the previous channel.
*/
public Channel prevChannel (int currentChannel) {
Channel channel = new Channel(currentChannel-1);
return channel;
}
}// End of class

/**
* RemoteControl class is the actual remote control and it behaves and makes
* use of ChannelSurfer.
*/
public class RemoteControl {
private ChannelSurfer surfer;
private Settings settings;

public RemoteControl() {
surfer = new ChannelSurfer();
settings = new Settings();
}
/**
* getProgram returns the program for that channel.
*
*/
public getProgram(ChannelSurfer surfer) {
return new Program(surfer.nextChannel());
}
}// End of class

We all know that every channel is associated to a program and it’s basically the program and not the
channel number which a user wants to see. And so, the implementation which returns a program for
channels surfed.

This tells us that we can apply some logic before returning the elements through iterator. We can set
rules. The Iterator here, can also be programmed to return the ‘programs’ straight away rather than
returning the channels.

The common Java iterator is Enumeration which has implicit


hasMoreElements()
and nextElement() methods.

2
The benefits of Iterator are about their strength to provide a common interface for iterating through
collections without bothering about underlying implementation.

But why?
The iterator separates out the functionality of stepping through a group of items into its own class -
promoting one-class, one-responsibility design which gives the aggregate only one reason to change itself
instead of two. Separating iteration out encapsulates the functionality so that clients can expect
predictable results when reviewing a collection, which promotes polymorphism.

OK, and how is it implemented?

• Ruby
• .Net

//Java

//create a concrete aggregate class


public class BookList {
//create a collection of books
Hashtable bookItems = new Hashtable();

public BookList() {
//constructor code
}

public void addBook(Book book) {


//add the book to the collection
bookItems.put(book.getISBN(), book);
}

//Return an iterator to step through book list.


//The booklist uses a hashtable to contain its collection,
//another object (say customerList) may use an arraylist
//for its collection. By creating an generic iterator for both
//concrete aggregate objects, it promotes polymorphism.
public Iterator createIterator() {
//iterate through just the book items
return bookItmes.values().iterator();
}
}

//Our booklist uses a hastable, which provides its own iterator method.
//a more generic collection may need its own iterator created, something
//like this:
public class BookShelfIterator implements Iterator {
BookShelf[] list;
int position = 0;

public BookShelfIterator(BookShelf[] list) {


this.list = list;
}

public Object next() {


//implementation here
}

public boolean hasNext() {


//implementation here
}

3
}

//the iterator interface for BookShelfIterator:


public interface Iterator {
boolean hasNext();
Object newt();
}

Iterator

Motivation
One of the most common data structures in software development is what is generic called a collection. A
collection is just a grouping of some objects. They can have the same type or they can be all cast to a
base type like object. A collection can be a list, an array, a tree and the examples can continue.

But what is more important is that a collection should provide a way to access its elements without
exposing its internal structure. We should have a mechanism to traverse in the same way a list or an
array. It doesn't matter how they are internally represented.

The idea of the iterator pattern is to take the responsibility of accessing and passing trough the objects of
the collection and put it in the iterator object. The iterator object will maintain the state of the iteration,
keeping track of the current item and having a way of identifying what elements are next to be iterated.

Intent
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying
representation.

The abstraction provided by the iterator pattern allows you to modify the collection implementation
without making any changes outside of collection. It enables you to create a general purpose GUI
component that will be able to iterate through any collection of the application.

Implementation

Applicability & Examples


The iterator pattern allow us to:

4
• access contents of a collection without exposing its internal structure.
• support multiple simultaneous traversals of a collection.
• provide a uniform interface for traversing different collection.

Example 1: This exmple is using a collection of books and it uses an iterator to iterate through the
collection. The main actors are:

• IIterator - This interface represent the AbstractIterator, defining the iterator


• BookIterator - This is the implementation of Iterator(implements the IIterator interface)
• IContainer - This is an interface defining the Agregate
• BooksCollection - An implementation of the collection

Here is the code for the abstractions IIterator and IContainer:

interface IIterator
{
public boolean hasNext();
public Object next();
}

interface IContainer
{
public IIterator createIterator();
}

And here is the code for concrete classes for iterator and collection. Please note that the concrete iterator
is an nested class. This way it can access all the members of the collection and it is encapsulated so other
classes can not access the BookIterator. All the classes are not aware of BookIterator they uses the
IIterator:

class BooksCollection implements IContainer


{
private String m_titles[] = {"Design Patterns","1","2","3","4"};

public IIterator createIterator()


{
BookIterator result = new BookIterator();
return result;
}

private class BookIterator implements IIterator


{
private int m_position;

public boolean hasNext()


{
if (m_position < m_titles.length)
return true;
else
return false;
}
public Object next()
{
if (this.hasNext())
return m_titles[m_position++];
else
return null;
}
}
}

5
Specific problems and implementation

Iterator and multithreading


Several problems may appear when collections are added from different threads. First of all let's see which
the basic steps when using an iterator are:

• Step one: the collection return a new iterator (using in our example the createIterator method).
Usually this step is not affected when it is used in multithreading environments because it returns
a new iterator object.
• Step two: The iterator is used for iterating through the objects. Since the iterators are different
objects this step is not a problematic one in multithreading environments.

It seems that the iterator does not raise special problems when a collection is used from different threads.
Of course here we are talking about an "seems". To reformulate the iterator does not raise special
problems when the collection used from different threads as long the collection is not changed.

Let's analyze each case:

• A new element is added to the collection (at the end). The iterator should be aware of the new
size of the collection and to iterate till the end.
• A new element is added to the collection before the current element. In this case all the iterators
of the collection should be aware of this.

The same actions should occur when an element is removed from the collection. The iterators should be
aware of the changes.

The main task when creating a multithreading iterator is to create a robust iterator (that allows insertions
and deletions without affection transversal). Then the blocks which are changing or accessing resources
changed by another thread have to be synchronized.

External vs. internal iterators.


External Iterators - when the iteration is controlled by the collection object we say that we have an
external Iterator.

In languages like .net on java it's very easy to create external iterators. In our classical implementation an
external iterator is implemented. In the following example an external iterator is used:
// using iterators for a clloection of String objects:
// using in a for loop
for (Iterator it = options.iterator(); it.hasNext(); ) {
String name = (String)it.next();
System.out.println(name);
}

// using in while loop


Iterator name = options.iterator();
while (name.hasNext() ){
System.out.println(name.next() );
}

// using in a for-each loop (syntax available from java 1.5 and above)
for (Object item : options)
System.out.println(((String)item));

Internal Iterators - When the iterator controls it we have an internal iterator

On the other side implementing and using internal iterators is really difficult. When an internal iterator is
used it means that the code is be run is delegated to the aggregate object. For example in languages that
offer support for this is easy to call internal iterators:
collection do: [:each | each doSomething] (Smalltalk)

The main idea is to pass the code to be executed to the collection. Then the collection will call internally
the doSomething method on each of the components. In C++ it's possible to send the doMethod method

6
as a pointer. In C# .NET or VB.NET it is possible to send the method as a delegate. In java the Functor
design pattern has to be used. The main idea is to create a base Interface with only one method
(doSomething). Then the method will be implemented in a class which implements the interface and the
class will be passed to the collection to iterate. For more details see the Functor design pattern.

Who defines the traversal algorithm?


The algorithm for traversing the aggregate can be implemented in the iterator or in the aggregate itself.
When the traversal algorithm is defined in the aggregate, the iterator is used only to store the state of the
iterator. This kind of iterator is called a cursor because it points to the current position in the aggregate.

The other option is to implement the traversal algorithm in the iterator. This option offers certain
advantages and some disadvantages. For example it is easier to implement different algorithms to reuse
the same iterators on different aggregates and to subclass the iterator in order to change its behavior. The
main disadvantage is that the iterator will have to access internal members of the aggregate. In Java
and .NET this can be done, without violating the encapsulation principle, by making the iterator an inner
class of the aggregate class.

Robust Iterators
- Can the aggregate be modified while a traversal is ongoing? An iterator that allows insertion and
deletions without affecting the traversal and without making a copy of the aggregate is called a robust
iterator. A robust iterator will make sure that when elements are added or removed from an aggregate
during iteration; elements are not accessed twice or ignored.

Lets' say we don't need a robust iterator. If the aggregate can not be modified (because the iteration is
started), it should be made explicitly, meaning that the client should be aware of it. We can just return a
false value what an element is added to the collection stating that the operation has failed, or we can
throw an exception.

An alternative solution is to add functions to change the aggregate in the iterator itself. For example we
can add the following methods to our iterator:
bool remove();
bool insertAfer();
bool insertBefore();
In the case when this solution is chosen the iterator handles the changes of the aggregator. In this case
the operation to change the iteration should be added to the iterator interface or base class not to the
implementation only, in order to have a general mechanism for the entire application.

Mechanism provided by the programming language


The iterator pattern can be implemented from scrach in Java or .NET, but there is already built-in support
for Iterator Pattern (IEnumerator/IEnumerable in .NET and Iterator/Collection in JAVA).

Iterator Pattern

Definition

Provide a way to move through a list of collection or aggregated objects without knowing its internal
representations.

Where to use & benefits

• Use a standard interface to represent data objects.


• Use s standard iterator built in each standard collection, like List, Sort, or Map.
• Need to distinguish variations in the traversal of an aggregate.
• Similar to Enumeration class, but more effective.
• Need to filter out some info from an aggregated collection.

7
Example

Employee is an interface, Manager, PieceWorker, HourlyWorker and CommissionWorker are


implementation classes of interface Employee. EmployeeTest class will create a list and use a built-in
iterator of ArrayList class to traverse the members of the list.

import java.util.*;
interface Employee {
public abstract double earnings();
}
class Manager implements Employee {
private double weeklySalary;
private String name;
public Manager(String name, double s) {
this.name = name;
setWeeklySalary(s);
}

void setWeeklySalary(double s) {
if (s > 0) {
weeklySalary = s;
} else
weeklySalary = 0;
}

public double earnings() {


return weeklySalary;
}
public String getName() {
return name;
}
public String toString() {
return "Manager: " + getName();
}
}

class PieceWorker implements Employee {


private double wagePerPiece;
private int quantity;
private String name;
public PieceWorker(String name, double w, int q) {
this.name = name;
setWagePerPiece(w);
setQuantity(q);
}

void setWagePerPiece(double w) {
if (w > 0)
wagePerPiece = w;
else
wagePerPiece = 0;
}

void setQuantity(int q) {
if ( q > 0)
quantity = q;
else
quantity = 0;
}
public String getName() {
return name;
}
public double earnings() {
return quantity * wagePerPiece;
}

8
public String toString() {
return "Piece worker: " + getName();
}
}

class HourlyWorker implements Employee {


private double hourlyWage;
private double hours;
private String name;
public HourlyWorker(String name, double w, double h) {
this.name = name;
setHourlyWage(w);
setHours(h);
}

void setHourlyWage(double w) {
if (w > 0)
hourlyWage = w;
else
hourlyWage = 0;
}

void setHours(double h) {
if ( 0 <= h && h < 168)
hours = h;
else
hours = 0;
}
public String getName() {
return name;
}
public double earnings() {
return hourlyWage * hours;
}
public String toString() {
return "Hourly worker: " + getName();
}
}

class CommissionWorker implements Employee {


private double salary;
private double commission;
private double totalSales;
private String name;
public CommissionWorker(String name,
double salary, double commission, double totalSales) {
this.name = name;
setSalary(salary);
setCommission(commission);
setTotalSales(totalSales);
}
void setSalary(double s) {
if( s > 0)
salary = s;
else
salary = 0;
}
void setCommission(double c) {
if ( c > 0)
commission = c;
else
commission = 0;
}
void setTotalSales(double ts) {
if (ts > 0 )

9
totalSales = ts;
else
totalSales = 0;
}
public String getName() {
return name;
}
public double earnings() {
return salary + commission/100*totalSales;
}
public String toString() {
return "Commission worker:"
+ getName();
}
}

class EmployeeTest {
public static void main(String[] args) {
java.util.List list = new ArrayList();
list.add(new Manager("Bill", 800.00));
list.add(new CommissionWorker("Newt", 400.0, 3.75, 159.99));
list.add(new PieceWorker("Al", 2.5, 200));
list.add(new HourlyWorker("Babara", 13.75, 40));
list.add(new Manager("Peter", 1200.00));
list.add(new CommissionWorker("Margret", 600.0,5.5, 200.25));
list.add(new PieceWorker("Mark", 4.5, 333));
list.add(new HourlyWorker("William", 31.25, 50));

System.out.println("Use built-in iterator:");


Iterator iterator = list.iterator();
while(iterator.hasNext()) {
Employee em = (Employee)iterator.next();
System.out.print(em + " earns $");
System.out.println(em. earnings());
}
}
}
%java EmployeeTest
Use built-in iterator:
Manager: Bill earns $800.0
Commission worker:Newt earns $405.999625
Piece worker: Al earns $500.0
Hourly worker: Babara earns $550.0
Manager: Peter earns $1200.0
Commission worker:Margret earns $611.01375
Piece worker: Mark earns $1498.5
Hourly worker: William earns $1562.5

The above example also shows a dynamic binding feature which is popular in Object-Oriented realm.

If you want to pick up a specific object from the aggregated list, you may use the following code.

while(iterator.hasNext()) {
Employee em = (Employee)iterator.next();
if (em instanceof Manager) {
System.out.print(em + " earns $");
System.out.println(em. earnings());
}
}

The above list can also be replaced by an array and achieve the same result.

10

You might also like