Iteratorパターン
Iteratorパターンは、要素を列挙する手段を独立させるデザインパターンです。
自分なりにIteratorパターンをクラス図にまとめてみました。
Iteratorパターンのクラス図
Iteratorパターンの解説
AggregateインターフェースではIterator型のオブジェクトを返す抽象メソッド(createIterator)を定義している。このAggregateインターフェースを継承するAggregate1,2はリスト形式のような複数の値をもつクラスである。このクラスでcreateIteratorメソッドをオーバーライドし、その戻り値のIteratorオブジェクトの属性に自身(Aggregate1,2オブジェクト)を持たせる。
Iterator1,2クラスでは属性のAggregate1,2の中身の次の値を返すnextメソッドや、次の値の存在をチェックするhasNextメソッドを定義する。これは、Iterateインターフェースで定義している抽象メソッドnext,hasNextの実装である。
Iterator型のクラスではnext,hasNext以外にも、Aggregate型を走査して取得できる様々な値を返すメソッドを追加で作成することもできる(例えば現在の値を取得するcurrentメソッドなど)。
このようなクラスを作成すると、Aggregate1,2クラスの値を一つずつ取り出したい場合、
Aggregate1,2オブジェクトのcreateIteratorメソッドを実行しIterator1,2オブジェクトを取得する。
Iterator1,2のnextメソッドをwhile文などの繰り返し処理で取得すれば、各々要素を一つずつ取り出せる。
Iteratorパターンをどういう場合に使うか
Aggregateオブジェクトの要素を1つずつ取り出すような繰り返し処理を、indexの昇順で値を取り出していたとします。その後、取り出し方が変わり、indexの降順に値を取り出す必要が出てきたとします。そういった場合、取り出し方はIteratorクラスで定義しているので、呼び出し側の処理は変更する必要がなくなります。もしくは取り出し方が何パターンも出てきた場合(例えば、ユーザオブジェクトを年齢順に取り出したり、身長順に取り出したり、体重順に取り出したりする場合など)は、それらのIteratorクラスを作成することで、取り出し方と呼び出し処理を独立させることができます。
ただし、クラス図に書いたような各クラスは既に言語のUtilクラスとして用意されていることが多いため、自分で実装するという機会はあまりないかもしれません。
PlantUMLでIteratorパターンのクラス図を記述する
文頭のIteratorパターンのクラス図をPlantUMLで書いたときのソースです。
@startuml Iterator
interface Iterator{
+ {abstract} next(): Object
+ {abstract} hasNext(): boolean
}
class Iterator1 implements Iterator{
- aggregate : Aggregate1
--
+ next():
+ hasNext(): boolean
}
class Iterator2 implements Iterator{
- aggregate : Aggregate2
--
+ next():
+ hasNext(): boolean
}
interface Aggregate{
+ {abstract} createIterator(): Iterator
}
class Aggregate1 implements Aggregate{
+ createIterator(): Iterator
}
class Aggregate2 implements Aggregate{
+ createIterator(): Iterator
}
Aggregate -r.> Iterator : create >
Aggregate1 -r.> Iterator1 : create >
Iterator1 o-- Aggregate1
Aggregate2 -r.> Iterator2 : create >
Iterator2 o-- Aggregate2
@enduml
参考サイトURL
PHPによるデザインパターン入門 – Iterator〜順々にアクセスする
Iterator パターン – Wikipedia