はじめに
GoFのデザインパターンがまとめられたJava言語で学ぶデザインパターン入門で学んだことをまとめていきたいと思います。
参考書に沿ってJavaで説明していきますが、何か気になる箇所や改善点があれば気軽にコメントもらえると幸いです
まとめ一覧はこちら
Iteratorパターン
Iteratorとは
単語自体は繰り返す、反復するなどの意味を持ち、集約したオブジェクトを列挙する手段を提供するデザインパターンです。
次のような場合にIteratorパターンに準拠して実装するべきだと考えられます。
- アプリケーション固有なデータ、構造を持ったオブジェクトにアクセスをする場合
- 配列やコレクションなどの集合する要素にアクセスする場合(配列はforループで回せるが、リストなどのコレクションは難しかったりする)
- 集合の要素に順次にアクセスする必要がある場合
Iteratorパターンのクラス図
- ConcreteAggregateクラスでConcreteIteratorクラス(要素にアクセスする役割)のインスタンス生成
- Iteratorの必要性については後述
具体例
- ConcreteAggregateクラス : BookShelf(本棚)
- BookShelfクラスは複数のBookクラスを持つ
- ConcreteIteratorクラス : BookShelfIterator
今回のIteratorで用いる汎用メソッドはこの二つです
- 1. `next()`
- 次の要素を返す(現在の要素を返し、次の位置に進める)
- 2. `hasNext()`
- 次の要素が存在するか調べ、真偽値を返す
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
デザインパターン
- 生成に関するパターン
- Abstract factory
- Builder
- Factory Method
- Prototype
- Singleton
- 構造に関するパターン
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
- 振る舞いに関するパターン
- Chain of responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor