Imagine that you are game developer. Your game is war stategy. Army has complicated structure: it consists with Hero and three Groups. When King gives 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 structure of your army – you want some SoldiersIterator to loop through all soldiers in it. Red line is the Iterator (in my mind representation).

Usage

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 main purpose of Iterator.

    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. Code below represents instantiating of Army:

    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 class derived from Soldier and has only one difference – higher health level:



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.

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 standart and classic?

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

The way I created Iterator looked like

   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:

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

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

   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

If you haven't subsribed yet, you can subsribe below: