Iterator -1つ1つ数え上げる-
Java言語で学ぶデザインパターン入門 の第1章を参考にしました。
Iteratorパターンとは
本書には、以下のように記載されています。
何かがたくさん集まっているときに、それを順番に指し示していき、全体をスキャンする処理を行うもの。
簡単に言うと、for文を一般化したような感じですね。 Iterateとは、繰り返すという意味、Iteratorとは、反復子という意味です。 特徴として、数え上げの仕組みがAggregate役の外に置かれています(詳細は後述)。
Iteratorパターンの登場人物
実装
こちらを参考にしてください。
なぜIteratorパターンを使うのか?
以下のコードはIteratorパターンを使ったMainクラスです。
public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("Around the World in 80 Days")); bookShelf.appendBook(new Book("Bible")); bookShelf.appendBook(new Book("Cinderella")); bookShelf.appendBook(new Book("Daddy-Long-Legs")); Iterator it = bookShelf.iterator(); while (it.hasNext()) { Book book = (Book)it.next(); System.out.println(book.getName()); } } }
一方、こちらのコードは素直にfor文を回しているMain2クラスです。
public class Main2 { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("Around the World in 80 Days")); bookShelf.appendBook(new Book("Bible")); bookShelf.appendBook(new Book("Cinderella")); bookShelf.appendBook(new Book("Daddy-Long-Legs")); for (int i = 0; i < bookShelf.getLength(); i++) { Book book = bookShelf.getBookAt(i); System.out.println(book.getName()); } } }
この二つのコードの大きな違いは、ループ部分です。 一見すると、抽象クラスなどややこしいものを使用していないMain2クラスの方が優れているように見えます。 しかし、オブジェクト指向的には、Mainクラスの方が優れた設計であると言えます。
では、なぜIteratorを使うのでしょうか? それは、MainクラスがBookShelfの実装に依存していないからです。
Mainクラスでは、BookShelfクラスのメソッドを使用していません。 しかし、Main2クラスでは、BookShelfクラスのメソッド(getLength()やgetBookAt())を使用しています。 つまり、Main2クラスはBookShelfクラスに依存していることになります。
これの何が問題なのでしょうか? 例えば、BookShelfの実装を配列ではなく、java.util.Vectorを使うように変更したり、 プログラムからではなくDBなど外部から参照するように変更した場合、 Main2クラスでは、ループ部分まで変更する必要があります。 しかし、Mainクラスでは、BookShelfがどのような変更をされようともiteratorメソッドを持っており、 正しいIterator(hasNext()とnext()を実装しているクラスのインスタンス)を返してくれればループ部分の実装を変更する必要がありません。
しかし、Mainクラスを使用した場合でもBookShelfクラスに変更があれば、BookShelgIteratorクラスは変更しなければなりません。 結局、MainクラスでもMain2クラスでも変更する点は多いじゃん!となりますね(笑)
ですが、今回の論点は変更点の多さではなく、依存度についてです。 各クラスの依存度を下げることにより、クラスの再利用化が促進されます。 これこそオブジェクト指向の三大要素の一つであるポリモーフィズムですね。