I have been wondering what it is that makes the Iterator special when compared to other similar constructs, and that made the Gang of Four list it as a design pattern.
The Iterator is based on polymorphism (a hierarchy of collections with a common interface) and separation of concerns (iterating over the collections should be independent from the way the data is structured).
But what if we replace the hierarchy of collections with, for example, a hierarchy of mathematical objects (integer, float, complex, matrix etc.) and the iterator by a class representing some related operations on these objects, for example power functions. The class diagram would be the same.
We could probably find many more similar examples like Writer, Painter, Encoder, and probably better ones, that work the same way. However I have never heard any of these being called a Design Pattern.
So what makes the Iterator special?
Is it the fact that it is more complicated because it requires mutable state for storing the current position within the collection? But then, mutable state is usually not being considered desirable.
To clarify my point, let me give a more detailed example.
Here's our design problem:
Let's say we have a hierarchy of classes and an operation defined on the objects of these classes. The interface of this operation is the same for each class, but the implementations can be completely different. It is also assumed that it makes sense to apply the operation multiple times on the same object, say with different parameters.
Here's a sensible solution for our design problem (practically a generalization of the iterator pattern):
For separation of concerns, the implementations of the operation should not be added as functions to the original class hierarchy (operand objects). Since we want to apply the operation multiple times on the same operand, it should be represented by an object holding a reference to the operand, not just by a function. Therefore the operand object should provide a function that returns the object representing the operation. This object provides a function that performs the actual operation.
An example:
There's a base class or interface MathObject
(stupid name, I know, maybe someone has a better idea.) with derived classes MyInteger
and MyMatrix
. For each MathObject
an operation Power
should be defined that allows calculation of square, cube and so on. So we could write (in Java):
MathObject i = new MyInteger(5);
Power powerOfFive = i.getPower();
MyInteger square = powerOfFive.calculate(2); // should return 25
MyInteger cube = powerOfFive.calculate(3); // should return 125
Best Answer
Most of the patterns from the GoF book have the following things in common:
The problems solved by these patterns are so basic that many developers understand them mainly as workarounds for missing programming language features, which is IMHO a valid point of view (note that the GoF book is from 1995, where Java and C++ did not offer so many features as today).
The iterator pattern fits well into this description: it solves a basic problem which occurs very often, independently from any specific domain, and as you wrote by yourself it is a good example for "separation of concerns". As you surely know, direct iterator support is something you find in a lot of contempary programming languages today.
Now compare this to the problems you picked:
Moreover, I do not see anything in your power function example which could not be interpreted as an application of the strategy pattern or the command pattern, which means those basic parts are already in the GoF book. A better solution might contain either operator overloading or extension methods, but those are things are subject to language features, and that is exactly what the "OO means" used by the "Gang" could not provide.