ようこそ。睡眠不足なプログラマのチラ裏です。

デザインパターン第10回「Iteratorパターン」その1

後に書いた、デザインパターン第15回「Iteratorパターン」その2はこちらです。



なんだかんだで10回目を迎えましたデザパタ講座です。
さて今回は、GoFデザインパターンより「Iteratorパターン」をぬるーく解説します。


Iteratorパターンは、集約オブジェクトの内部表現を公開せずに、
集約オブジェクトの要素に対して順次アクセスする方法を提供するパターンです。
.NET Frameworkにおいては、イテレータ用のインターフェイスがあらかじめ用意されているので、
あわせてIEnumerableインターフェイスおよび、IEnumeratorインターフェイスについても触れておきます。


Iteratorパターンの概要■
Iteratorとは、「反復(繰り返し)」を意味する言葉です。
このパターンでは集合体(Aggregate)と、集合体の要素を列挙するもの(Iterator)が登場します。


このパターンは要素の集合体(Aggregate)の中の要素を、1つ1つ取り出しながら集合体を順次走査するパターンです。
つまり、メンバー変数へのアクセスを、外部クラスに委譲します。
ランダムアクセスの場合は、サイズを返すメソッドや指定位置のメソッドが必要になりますが、
このような順次アクセスの場合はその必要がなく、現在のカーソル位置を外部クラスに保持させます。
よって、このパターンは、全体のサイズが把握できないストリームや、一括ではなく順次データを返すケースに有効です。

Iterator パターンと foreach文

C#VB.NETには、Collection系オブジェクトの要素に対して順次アクセスするための構文として、
foreach(For Each...In...Next)文がありますが、JavaでのIteratorの基本的な使用法は以下のような感じになります。

[Java]
Iterator iterator = SampleAggreegate.iterator();

for ( iterator.First(); !iterator.IsDone(); iterator.Next())
{
  object obj = iterator.CurrentItem();
  System.out.println ("value:" + obj.Value);
}


しかし C#VB.NETのforeach(For Each...In...Next)文では、
これよりももっと簡素に書くことができます。
C#VB.NETでコレクションの要素を走査するには以下のように書きます。

[C#]
foreach ( Object obj in SampleCollection){
 System.Console.Write("value:{0}", obj.ToString());
}

[VB.NET]
For Each obj as Object In SampleCollection
  System.Console.Write("value:{0}",obj.ToString())
Next

Java のコードと比べるとIteratorに対して操作する部分が完全に無くなって、簡素になっています。
この例に出てくる SampleCollection とは Iterator パターンの 具象集合体(ConcreteAggregate)を指します。
そして Iterator は foreach(For Each...In...Next)文に隠されています。
Iteratorが隠されてしまうのはいい事ばかりではないですが、そのお陰でいっそう簡素に処理を記述できるようになっています。*1


foreach 文で回せるコレクションを作る
.NET Framework のライブラリには、System.Collections名前空間に、
IEnumerableインターフェイス (Aggregate)および、IEnumeratorインターフェイス (Iterator)が用意されています。


C#のforeachセマンティクスおよび、VB.NETのForEach セマンティクスをサポートするには、
IEnumerableインターフェイスを実装する必要があります。
IEnumerableインターフェイスでは、コレクションに対する単純な反復処理をサポートする列挙子を公開するようにします。
また、COMクラスで列挙子を使用できるようにする場合にも、このインターフェイスを実装する必要があります。
IEnumeratorインターフェイスでは、コレクションに対する単純な反復処理をサポートします。
MoveNext()抽象メソッドには、 列挙子をコレクションの次の要素に進める処理を記述します。
Reset()抽象メソッドには、列挙子を初期位置、つまりコレクションの最初の要素の前に設定する処理を記述します。


これらのインターフェイスを実装し、ConcreteAggregateおよびConcreteIteratorを作ることによって、
foreach(For Each...In...Next)文で使用可能なコレクションを作ることができます。
では、詳しくはオマケ参照ということで…(´・ω・`)


オマケ
Iteratorパターン - VB.NET - 雑なサンプルソース

*1:.NET Frameworkでは、Iterator パターンを文法レベルでサポートしていると解釈できます