February 13, 2010 Design Patterns
February 13, 2010 Design Patterns
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 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.
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:
Hero is class derived from Soldier and has only one difference – higher health level:
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.
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
But generally this logic could be hidden under some Aggregate’s method (like GetEnumerator in .NET). For example I could have this:
In .NET world we have IEnumerable<T> and IEnumerator<T> interfaces which provides a lot of help in impementing this pattern:
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 :).
Markdown | Result |
---|---|
*text* | text |
**text** | text |
***text*** | text |
`code` | code |
~~~ more code ~~~~ |
more code |
[Link](https://www.example.com) | Link |
* Listitem |
|
> Quote | Quote |
I don't see difference between your "soldiers iterator" and standard iterator.
leonidv, I'm not 100% percents sure what you mean my "standard iterator".
But, as I understand your question there is no difference between them. My "soldiers iterator" behaves like usual Concrete Iterator from GoF. What I mean here is that whole pattern was developed by me in much easier way than it is developed in GoF.
Sorry if I introduced confusion by those my statements.
Thanks, for comment.