Help us understand the problem. What is going on with this article?

デザインパターン「Iterator」

More than 3 years have 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言語で学ぶデザインパターン入門

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away