Edited at

デザインパターン「Iterator」

More than 1 year has passed since last update.


はじめに

GoFのデザインパターンがまとめられたJava言語で学ぶデザインパターン入門で学んだことをまとめていきたいと思います。

参考書に沿ってJavaで説明していきますが、何か気になる箇所や改善点があれば気軽にコメントもらえると幸いです

まとめ一覧はこちら


Iteratorパターン


Iteratorとは

単語自体は繰り返す反復するなどの意味を持ち、集約したオブジェクトを列挙する手段を提供するデザインパターンです。

次のような場合にIteratorパターンに準拠して実装するべきだと考えられます。


  • アプリケーション固有なデータ、構造を持ったオブジェクトにアクセスをする場合

  • 配列やコレクションなどの集合する要素にアクセスする場合(配列はforループで回せるが、リストなどのコレクションは難しかったりする)

  • 集合の要素に順次にアクセスする必要がある場合


Iteratorパターンのクラス図

スクリーンショット 2016-02-06 23.08.21.png


  • ConcreteAggregateクラスでConcreteIteratorクラス(要素にアクセスする役割)のインスタンス生成

  • Iteratorの必要性については後述


具体例

今回のIteratorで用いる汎用メソッドはこの二つです




1. next()



次の要素を返す(現在の要素を返し、次の位置に進める)



2. hasNext()



次の要素が存在するか調べ、真偽値を返す





以下のようなIteratorのインスタンスが本棚の本を列挙していく例で説明していきます。


Mainクラス


Main.java

public static void main(String[] args) {

BookShelf bookShelf = new BookShelf(4);

bookShelf.appendBook(new Book("Git Hub"));
bookShelf.appendBook(new Book("Qiita"));
bookShelf.appendBook(new Book("Java"));
bookShelf.appendBook(new Book("Iterator pattern"));

Iterator iterator = bookShelf.iterator();
while(iterator.hasNext()) {
Book book = (Book)iterator.next();
System.out.println(book.getName());
}
}



抽象クラス


Aggregate.java

public interface Aggregate {

public abstract Iterator iterator();
}


Iterator.java

public interface Iterator {

public abstract boolean hasNext();
public abstract Object next();
}


具象クラス

本棚のクラス


  • Aggregateインタフェースを実装


BookShelf.java

public class BookShelf implements Aggregate {

private Book[] books;
private int last = 0;

public BookShelf(int maxsize) {
this.books = new Book[maxsize];
}

public Book getBookAt(int index) {
return books[index];
}

public void appendBook(Book book) {
this.books[last] = book;
last++;
}

public int getLength() {
return last;
}

public Iterator iterator() {
return new BookShelfIterator(this);
}
}


本のクラス


  • 今回は名前を返すだけのクラス


Book.java

public class Book {

private String name;

public Book(String name) {
this.name = name;
}

public String getName() {
return name;
}
}


本棚の要素にアクセスするクラス


  • Iteratorインタフェースを実装


BookShelfIterator.java

public class BookShelfIterator implements Iterator {

private BookShelf bookShelf;
private int index;

public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}

public boolean hasNext() {
if (index < bookShelf.getLength()) {
return true;
} else {
return false;
}
}

public Object next() {
Book book = bookShelf.getBookAt(index);
index++;
return book;
}
}



実行結果

Git Hub

Qiita
Java
Iterator pattern


追記


・Iterator役を生成することで利用側はConcreteAggregate(BookShelf)の実装を意識せず要素にアクセスできる

ループでBookShelfのメソッドは呼ばれていないので依存関係がない



・様々な要素の列挙が可能

最初(後)・全部の要素を返す、逆方向に探索、要素を指定してジャンプするなど

試しにBookShelfの実装を変えてみましょう

Bookの配列ではなくjava.util.ArrayListを用いてみます


BookShelf.java

import java.util.ArrayList;

public class BookShelf implements Aggregate {
private ArrayList books;

public BookShelf(int initialize) {
this.books = new ArrayList(initialize);
}

public Book getBookAt(int index) {
return (Book)books.get(index);
}

public void appendBook(Book book) {
books.add(book);
}

public int getLength() {
return books.size();
}

public Iterator iterator() {
return new BookShelfIterator(this);
}
}



実行結果

Mainクラスの実装は変えていませんが同じ結果が得られました。

Git Hub

Qiita
Java
Iterator pattern


サンプルコードについて

以下のレポジトリにソースコードをアップしてあります。

shoheiyokoyama/design-pattern_java


デザインパターン


参考文献

Java言語で学ぶデザインパターン入門