Iteratorパターンはデータの集合体に対して順番に走査する仕組みを作りたいときによく用いられる.たとえばJavaでは配列やリストなど基本的なデータ構造にIteratorパターンが実装されており,これにより拡張for文が実現していたりします.
Iteratorパターンの登場人物は主に次の4つになります.
- 集合体を表すAggregateインターフェース
- 走査をしていくIteratorインターフェース
- ある集合体を表す ConcreteAggregateクラス
- ある集合体を走査していくための具体的方法を実装したConcreteIteratorクラス
Iteratorパターンをある集合体に適用する場合,その集合体を走査するためのIteratorを生成して返すiteratorメソッドを必ず実装します. Iteratorインターフェースは次の要素が存在するかどうかのbooleanを返すhasNext(),今の要素を返して次の要素をポイントするnext()を持ちます.集合体により走査のしかた,方法などは不定なので,それぞれにあった走査の方法はConcreteIteratorクラスを作り,そちらで実装します.クラス図で表すと次のような具合になります.
具体例
具体例として,生徒Studentクラスの集合体:生徒一覧StudentListクラスに対して,Iteratorパターンを適用したコードを書いてみました.
// Aggregate.java
package DesignPattern.Iterator;
public interface Aggregate {
public abstract Iterator iterator();
}
// Iterator.java
package DesignPattern.Iterator;
public interface Iterator {
public abstract boolean hasNext();
public abstract Object next();
}
// Student.java
package DesignPattern.Iterator;
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
if (!name.equals(student.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
}
// StudentList.java
package DesignPattern.Iterator;
public class StudentList implements Aggregate {
private Student[] students;
private int last = 0;
public StudentList(int numOfStudents) {
this.students = new Student[numOfStudents];
}
public Student getStudent(int number) {
return students[number];
}
public void addStudent(Student student) {
this.students[last] = student;
last++;
}
public int getNumberOfStudents() {
return this.last;
}
@Override
public Iterator iterator() {
return new StudentListIterator(this);
}
}
// StudentListIterator.java
package DesignPattern.Iterator;
public class StudentListIterator implements Iterator {
private StudentList studentList;
private int index;
public StudentListIterator(StudentList studentList) {
this.studentList = studentList;
this.index = 0;
}
@Override
public boolean hasNext() {
if(index < studentList.getNumberOfStudents())
return true;
else
return false;
}
@Override
public Object next() {
Student student = studentList.getStudent(index);
index++;
return student;
}
}
クラス図は以下のような具合になります.
まとめ
- 肝になる部分は,集合とその数え上げ方(走査方法)が分離されているというところかな.
- ひとつの集合に対して,Iteratorを実装したものを複数作れば,色々な方法で走査ができるところは良いですね.