📜 ⬆️ ⬇️

Iterator

(Sorry for my Russian in advance)

Imagine that you are a developer of a strategic war game. The army has a complex structure: it consists of a hero and three groups. When the King issues a decree and resources to treat all warriors (The hero is also a warrior) you want to test all soldiers and call the treat () method on each instance. How can this be done easily and without understanding the structure of the army?

Iterator


')
An iterator is a pattern that allows access to the elements of any collection without understanding the essence of its implementation.
Thus applied to our problem: We do not want to experience the structure of the Army - we want SoldiersIterator to run through all the soldiers.

The red line in the figure is an iterator (at least as I imagine it).



Using



The code below shows the use of an iterator. As you can see, we just got an instance of the SoldiersIterator iterator. And a simple cycle passes through all the soldiers of the army. This is very easy, which is the main task of the iterator.

SoldiersIterator iterator = new SoldiersIterator(earthArmy);

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

* This source code was highlighted with Source Code Highlighter .


Army structure



An army consists of one hero and may contain several groups, each of which may contain many soldiers. So, as we can see, the structure of the army is complex and tree-like. The code below shows the creation of the 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);


* This source code was highlighted with Source Code Highlighter .


Hero (Hero) is a class of desaturation from a soldier (Soldier) and the main difference is that he has a higher level of health.

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);
}
}


* This source code was highlighted with Source Code Highlighter .


SoldiersIterator



Therefore, if we can move through a complex collection so easily, where is all the complexity?
Of course, it is hidden encapsulated in a specific 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;
}
}


* This source code was highlighted with Source Code Highlighter .


How does my example differ from the standard GoF?



Because I set myself the task to emphasize the main task that this pattern solves and to do it in such a way that it will be possible to easily all of them. Another reason is that you can read tons of standard explanations of this pattern. But the main difference between my explanation and other explanations is that the standard is more abstract.

For example, I created the iterator we need as follows:

SoldiersIterator iterator = new SoldiersIterator (earthArmy);

* This source code was highlighted with Source Code Highlighter .


But usually creating an iterator is also encapsulated under an aggregate method (like GetEnumerator in .NET). My code might look like this:

IIterator iterator = AbstractArmy.GetSoldiersIterator ();

* This source code was highlighted with Source Code Highlighter .


In the world. NET, we are the IEnumerable and IEnumerator interfaces that help us in using this pattern.

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


* This source code was highlighted with Source Code Highlighter .


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

Using this link I liked the explanations of the differences between these two languages:
http://www.25hoursaday.com/CsharpVsJava.html

My pattern plate

Source: https://habr.com/ru/post/84184/


All Articles