Click here to Skip to main content
15,883,603 members
Articles / All Topics

Iterator

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
16 Feb 2010CPOL2 min read 9.5K   5   3
Iterator

Imagine that you are a game developer. Your game is war strategy. Army has a complicated structure: it consists of Hero and three Groups. When King gives a decree to treat all soldiers (Hero is also soldier), you want to iterate through all soldiers and call treat() method on each soldier instance. How can this be accomplished easily and without diving into Army structure?

ITERATOR

Iterator is the pattern which provides you a way to access all elements in any collection of data without exposing collection implementation.

So in application to our problem. You just don't want to care about the structure of your army - you want some SoldiersIterator to loop through all soldiers in it. Red line is the Iterator (in my mind representation).

Image 1

Usage

The code below shows usage of iterator. We can loop through all soldiers and increase their health level without thinking of the structure of Army. This should be easy and it is the main purpose of Iterator.

C#
SoldiersIterator iterator = new SoldiersIterator(earthArmy);

while(iterator.hasNext()){
    Soldier currSoldier = iterator.next();
    currSoldier.treat();
}

Army Structure

Army structure has one Hero and could have many Groups which of them could have many Soldiers. So as we see, structure of Army is complicated and tree-based. The code below represents instantiating of Army:

C#
Army earthArmy = new Army();

Group groupA = new Group();
for(int i=1; i<4; ++i)
    groupA.addNewSoldier(new Soldier("Alpha:" + i));

Group groupB = new Group();
for(int i=1; i<3; ++i)
    groupB.addNewSoldier(new Soldier("Beta:" + i));

Group groupC = new Group();
for(int i=1; i<2; ++i)
    groupC.addNewSoldier(new Soldier("Gamma:" + i));

earthArmy.ArmyHero = new Hero("Andriy Buday");
earthArmy.addArmyGroup(groupB);
earthArmy.addArmyGroup(groupA);
earthArmy.addArmyGroup(groupC);

Hero is a class derived from Soldier and has only one difference - higher health level:

C#
public class Soldier {   
    public String Name;
    public int Health;
    protected int maxHealthPoints = 100;
  
    public Soldier(String name){
        Name = name;
    }   
  
    public void treat(){
        Health = maxHealthPoints;
        System.out.println(Name);
    }   
}

public class Hero extends Soldier {
    protected int maxHealthPoints = 500;
  
    public Hero(String name) {
        super(name);
    }
}

SoldiersIterator

So if we can move through the complicated collection of Soldiers, where is that complicity? Well, it is encapsulated in concrete Iterator class.

C#
public class SoldiersIterator {

    private Army _army;
    boolean heroIsIterated;
    int currentGroup;
    int currentGroupSoldier;

    public SoldiersIterator(Army army) {
        _army = army;
        heroIsIterated = false;
        currentGroup = 0;
        currentGroupSoldier = 0;
    }

    public boolean hasNext() {
        if(!heroIsIterated) return true;
        if(currentGroup < _army.ArmyGroups.size())return true;
        if(currentGroup == _army.ArmyGroups.size()-1)
            if(currentGroupSoldier < _army.ArmyGroups.get(currentGroup).Soldiers.size())return true;
      
        return false;
    }

    public Soldier next() {
        Soldier nextSoldier;
        // we still not iterated all soldiers in current group
        if (currentGroup < _army.ArmyGroups.size()) {
            if (currentGroupSoldier < _army.ArmyGroups.get(currentGroup).Soldiers.size()) {
            nextSoldier = _army.ArmyGroups.get(currentGroup).Soldiers.get(currentGroupSoldier);
            currentGroupSoldier++;
            }
            // moving to next group
            else {
            currentGroup++;
            currentGroupSoldier = 0;
            return next();
            }
        }
        // hero is the last who left the battlefield
        else if (!heroIsIterated) {
            heroIsIterated = true;
            return _army.ArmyHero;
        } else {
            // THROW EXCEPTION HERE
            throw new IllegalStateException("End of colletion");
            //or set all counters to 0 and start again, but not recommended 
        }
        return nextSoldier;
    }
}

Why My Example is Not Standard and Classic?

Because my goal in this article was to highlight the main issue that Iterator solves in such a manner that it could be easily understandable. And the second reason is that you can read tonnes of standard explanations of this Design Pattern. The main difference between my explanation and others is that classic explanation is more abstracted, it contains abstract Iterator which represents interface for concrete ones, and abstract Aggregate, which creates Iterators needed.

The way I created Iterator looked like:

C#
SoldiersIterator iterator = new SoldiersIterator(earthArmy);

But generally this logic could be hidden under some Aggregate's method (like GetEnumerator in .NET). For example, I could have this:

C#
AbstractIterator iterator = AbstractArmy.GetSoldiersIterator();// returns SoldiersIterator

In .NET world, we have IEnumerable<T> and IEnumerator<T> interfaces which provides a lot of help in implementing this pattern:

C#
var list = new List<int>();
//GetEnumerator is method of IEnumerator (Aggregate)
var enumerator = list.GetEnumerator();
//MoveNext method of IEnumerable (Iterator)
enumerator.MoveNext();

In Java, we have java.lang.Iterable instead of IEnumerable, which is more intuitive naming. I think that Microsoft just wanted to be original in this :).

My Design Patterns Table

This article was originally posted at http://andriybuday.blogspot.com/feeds/posts/default

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer SoftServe
Ukraine Ukraine
I'm very pragmatic and self-improving person. My goal is to become successful community developer.
I'm young and love learning, these are precondition to my success.

Currently I'm working in dedicated Ukrainian outsourcing company SoftServe as .NET developer on enterprise project. In everyday work I'm interacting with lot of technologies which are close to .NET (NHibernate, UnitTesting, StructureMap, WCF, Win/WebServices, and so on...)

Feel free to contact me.

Comments and Discussions

 
Generalold school ;} Pin
radioman.lt17-Feb-10 1:31
radioman.lt17-Feb-10 1:31 
GeneralRe: old school ;} Pin
Andriy Buday17-Feb-10 8:37
Andriy Buday17-Feb-10 8:37 
GeneralRe: old school ;} Pin
radioman.lt19-Feb-10 0:50
radioman.lt19-Feb-10 0:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.