PS: Anything beautiful becomes less precious when it becomes commonplace.
The iterator design pattern is a commonly used design pattern that provides a way to sequentially access various elements in an aggregate object without exposing the internal representation of the object. The iterator design pattern belongs to the behavioral design pattern.
- Related Concepts
- Use Cases
- Java Implementation
- Dart Implementation
Related Concepts#
- Abstract Aggregate Role: Defines methods for adding, deleting, and creating iterators for the aggregate object.
- Concrete Aggregate Role: Concrete implementation class of the abstract aggregate role.
- Abstract Iterator Role: Defines iterator-related methods, such as hasNext, first, last, etc.
- Concrete Iterator Role: Concrete implementation class of the abstract iterator role.
Use Cases#
The use cases of the iterator design pattern are as follows:
- Provide a traversal method for a specific data structure.
- Use the iterator design pattern to hide the implementation details of the aggregate object.
- When there are multiple aggregate objects, using the iterator design pattern can shield the differences caused by different data structures.
Java Implementation#
Implement the iterator design pattern simply. Define the abstract aggregate role as follows:
/**
* Abstract aggregate role
* Created by jzman
* Powered by 2019/12/22.
*/
interface Aggregate {
Iterator createIterator();
}
Define the abstract iterator role as follows:
/**
* Abstract iterator role
* Created by jzman
* Powered by 2019/12/22.
*/
interface Iterator {
Object first();
Object next();
boolean isDone();
Object currentItem();
}
Implement the concrete aggregate role and concrete iterator role as follows:
/**
* Concrete aggregate role
* Created by jzman
* Powered by 2019/12/22.
*/
class ConcreteAggregate implements Aggregate {
private List<Object> mList;
public ConcreteAggregate(List<Object> mList) {
this.mList = mList;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator();
}
/**
* Concrete iterator role
*/
private class ConcreteIterator implements Iterator {
private int mCursor;
@Override
public Object first() {
return mList.get(0);
}
@Override
public Object next() {
mCursor++;
if (mCursor < mList.size()) {
return mList.get(mCursor);
}
return null;
}
@Override
public boolean isDone() {
return mCursor >= mList.size();
}
@Override
public Object currentItem() {
return mList.get(mCursor);
}
}
}
Test the above code:
/**
* Iterator test
* Created by jzman
* Powered by 2019/12/22.
*/
class Client {
public static void main(String[] args) {
List<Object> objects = new ArrayList<>();
objects.add("A");
objects.add("B");
objects.add("C");
ConcreteAggregate aggregate = new ConcreteAggregate(objects);
// Get the iterator
Iterator iterator = aggregate.createIterator();
// Traverse
while (!iterator.isDone()) {
Object o = iterator.currentItem();
System.out.println("data:" + o);
iterator.next();
}
}
}
The test result is as follows:
data:A
data:B
data:C
Dart Implementation#
main(){
List<Object> mList = ["A","B","C"];
Aggregate aggregate = new ConcreteAggregate(mList);
Iterator iterator = aggregate.createIterator();
while (!iterator.isDone()) {
Object obj = iterator.currentItem();
print("data:${obj.toString()}");
iterator.next();
}
}
// Abstract iterator role
abstract class Iterator{
Object first();
Object next();
bool isDone();
Object currentItem();
}
// Concrete iterator role
class ConcreteIterator implements Iterator{
int mCursor = 0;
List<Object> mList;
ConcreteIterator(this.mList);
@override
Object first() {
return mList[0];
}
@override
Object next() {
mCursor++;
if (mCursor < mList.length) {
return mList[mCursor];
}
return null;
}
@override
bool isDone() {
return mCursor >= mList.length;
}
@override
Object currentItem() {
return mList[mCursor];
}
}
// Abstract aggregate role
abstract class Aggregate {
Iterator createIterator();
}
// Concrete aggregate role
class ConcreteAggregate implements Aggregate{
List<Object> mList;
ConcreteAggregate(this.mList);
@override
Iterator createIterator(){
return new ConcreteIterator(mList);
}
}
The test result is as follows:
data:A
data:B
data:C
Although the iterator design pattern is often used when traversing collections, it may not have any concept of design patterns when used, but such concepts will subtly improve one's coding ability.