導入
Processingがバージョン3.
閑話休題。今回はGoFによるデザインパターン23種類のうち、
展開
Iterator(イテレータ)
前述したように、
Iteratorパターンの目的
iterateは
オブジェクトの集合を取り扱う際、
Java言語、
上のコード例ではIteratorパターンの存在が隠されています。このコードの裏ではIteratorパターンを利用して配列の要素の先頭から順にアクセスしています。
Iteratorパターンを使うと、
- 「
names[i]
として、配列というデータ構造の変数 names
の、
先頭からi
番目に納められたString
型のデータ」
とアクセスしていたところが、
- 「
String
型のデータv
」
で済みます。Iteratorパターンに従っていることが分かれば、
[Iteratorパターン]
複数のオブジェクトを順に取り扱う機能を抽象化したもの。
Java言語やProcessingでは、
GoFによるIteratorパターンの全体像
ここでは、
Java言語のクラスライブラリ中で実装されているIteratorパターンは、
下図はIteratorパターンを用いたコードのクラス図の一例です。
Iteratroパターンでは、ConcreteAggregate
クラスに納められたデータの集合をClient
クラスが順に取り出して処理することを目的とします。図の一番下にあるData
クラスが、ConcreteAggregate
クラスが保持するデータ保管用クラスです。Aggregateという英語は
Aggregate
インタフェイスのiterator
メソッドは、Iterator
インタフェイスを実装したConcreteIterator
オブジェクトを返します。ConcreteIterator
はConcreteAggregate
に納められたオブジェクト群にアクセスするコードを持っています。
結局Client
クラスがデータのアクセスに必要とするのは、ConcreteAggregate
オブジェクトと、ConcreteIterator
オブジェクトの参照を持つIterator
インタフェイスのオブジェクトです。
[Clientクラスがデータアクセスに必要とする情報] - ConcreteAggregateオブジェクトへの参照
- ConcreteAggregateオブジェクトのiteratorメソッドが返すConcreteIteratorへの参照
Iteratorパターンのメリット
この仕組みがあれば、ConcreteAggregate
クラスがどんな型やクラスのオブジェクト群を保持していても、Client
クラスから、Iterator
インタフェイスの持つhasNext
メソッドやnext
メソッドでオブジェクト群の巡回が可能になります。仮にConcreteAggregate
クラスが保持するオブジェクトの型が変更されても、ConcreteIterator
クラスのコードを修正しておけば、Client
クラスのコードでは、ConcreteAggregate
クラスの保持するデータの巡回のためのコードに変更が必要ありません。
チームでコーディングしている際に、ConcreteAggregate
クラス側の開発者も、
例えば、
「このクラスはIteratorパターンに従っています」
と言えば、iterator
メソッドがあり、ConcreteIterator
のオブジェクトを取得できるとわかります。後は、next
メソッドでオブジェクトを取得し、hasNext
メソッドで次のオブジェクトが取得可能かを知ることができます。
Java言語では、ConcreteIterator
にあたるオブジェクトを返すメソッドiterator
を実装しているクラスArrayList
やVector
など)iterator
メソッドを実装しなさいよ、Aggregate
インタフェイスにあたるのが、Iterable<T>
インタフェイスです。
ですから、ConcreteIterator
クラスを書かなくても、Client
クラスからオブジェクトを巡回するコードを簡単に書けるのです。
Java言語やProcessingで使われているIteratorパターンを見る
次のサンプルコードを見てください。
String
クラスのデータを納めるArrayList
オブジェクトA
を宣言し、
(1)は、i
を用いて要素を指定します。
(2)は、
(3)は、
注目してもらいたいのは、String
型のArrayList
のA
である」String
型のオブジェクトv
である」A
からConcreteIterator
オブジェクトへの参照を取得した後は、ConcreteIterator
オブジェクトの取得先を切り替えれば、
あなたのコードにGoFのIteratorパターンを使う
それでは、ADrawTool
とします。
- Iteratorパターンを適用したsketch
これにより、ExStatechartDiagram2.
のdraw
メソッド内のコードでは隠れていたIteratorが、ADrawTool.
では表に引っ張りだされました。
これらのサンプルコードでは、Point
クラスのオブジェクトp
に格納して点を描画するだけです。ExStatechartDiagram2.
では、ArrayList
が持っていたJava言語の持つIteratorパターンを利用した拡張for文を使ってデータを巡回するだけで事足りていました。
ca
はGoFによるIteratorパターンのAggregate
インタフェイスを実装したConcreteAggregate
クラスのオブジェクトですから、iterator
メソッドを持ちます。このiterator
メソッドを呼ぶと、Iterator
インタフェイスを実装したConcreteIterator
クラスのオブジェクトを返します。Iterator
インタフェイスのオブジェクトit
が持つConcreteIterator
オブジェクトへの参照を用いて、while
ループ内で各点の示すディスプレイウインドウ内の座標に点を描きます。
GoFによるデザインパターンのIteratorを忠実に適用したので、ADrawTool.
のコードは冗長になっています。これだけではIteratorパターンを見える化した利益はありません。
このADrawTool.
を発展させ、Iterator
インタフェイスを使っていると、Iterator
インタフェイスがほしくなります。
それでは独自のIteratorパターンを用いるメリットがある活動に入ります。データ群を逆順に巡回するための、hasPrevious
previous
goTail
メソッドとしましょう。それならば、goHead
メソッドとします。これらをインタフェイスIterator
に用意し、ConcreteIterator
へ実装しましょう。これらのメソッドを実装するクラスは、Client
側にあたるADrawTool
のコードからはIterator
インタフェイスを通じて、ca
にアクセスできます。Iteratorパターンを利用する側のコードは、
演習
演習1(難易度:middle)
sketchADrawTool
のIterator
インタフェイスにhasPrevious
, previous
, goHead
, goTail
の各メソッド宣言を用意し、ConcreteIterator
クラスにそれらを実装しましょう。
まとめ
- Iteratorパターンのメリットと使い方を学びました。
学習の確認
それぞれの項目で、
- Iteratorパターンのメリットがわかりましたか?
- わかりました。自分のプログラミングにも活用したい。
- 解説を理解することはできたが、
それほどメリットを感じない。 - 本文が理解できない。
- Iteratorパターンを使えるようになりましたか?
- 使えるようになった。自分のプログラミングにも活用できそうだ。
- 本文の例を理解することはできたが、
自分のプログラミングに活用できる気がしない。 - 本文の例が理解できない。
参考文献
- 『増補改訂版Java言語で学ぶデザインパターン入門』
(結城浩 著、 ソフトバンククリエイティブ) - 誰もが認める最も分かりやすいデザインパターン入門書。本来は原典
(GoF本) を勧めるべきところですが、 本書は別格。
- 誰もが認める最も分かりやすいデザインパターン入門書。本来は原典
- 『オブジェクト指向における再利用のためのデザインパターン』
(Eric Gamma 著、 ソフトバンククリエイティブ) - デザインパターンの原典。別称
『GoF本』 サンプルコードがC++で書かれているため、 ProcessingやJava言語のユーザにはハンディがあります。しかし結城浩氏の入門書を読みこなした後ならば本書にあたる価値があります。
- デザインパターンの原典。別称
- 『Java デザインパターン徹底攻略』
(日立ソフトウェアエンジニアリング (株) インターネットビジネス部 著、 技術評論社) - 流石の日立。前掲のGoF本の解説書で、
サンプルはJava言語。絶版であることが惜しまれます。強く再版を望みます。
- 流石の日立。前掲のGoF本の解説書で、
演習解答
- 追加した
hasPrevious
,previous
,goHead
,goTail
が動作するかをチェックするテストコードConcreteIteratorTest.
を追加しています。pde