2012年11月21日水曜日

Iteratorパターン(イテレータ・パターン)

Iteratorパターンは振る舞いに関するデザインパターンのひとつです。

ある集合体の要素1つ1つに、順次アクセスする方法
     for (int i = 0; i < data.length; i++) {
         System.out.println(data[i]);
     }
こういうのを、集合体で実現するためのパターンです。

Iteratorパターン
Iteratorパターン 図のソース(dot)
 
クラス図左側
・Aggregate(集合体)・・・Iteratorを作り出すインタフェース
・ConcreteAggregate(具体的な集合体)・・・Aggregateを実装したクラス
     iteratorメソッド:ConcreteIteratorオブジェクトを返す。

クラス図右側
・Iterator(反復子)・・・要素を順番にスキャンしていくインタフェース
・ConcreteIterator(具体的な反復子)・・・Iteratorを実装したクラス
    nextメソッド:indexの位置にあるオブジェクトを返し、indexをインクリメントする。
    hasNextメソッド:次の要素があればTrue、無ければFalseを返す。

-----------------
使用例       参考書籍:増補改訂版Java言語で学ぶデザインパターン入門

Iteratorパターン 使用例
Iteratorパターン使用例 図のソース(dot)
----------------------------------------------------------------------
集合体にしたいクラス

ファイル名:Book.java
 

      public class Book {

           // 本の名前
           private String name;
           // コンストラクタで本の名前を設定
           public Book(String name) {
               this.name = name;
           }

           // 本の名前を取得するメソッド
           public String getName() {
               return name;
           }
       }
--------------------------------------------------------------
Bookを集合体にするクラス

ファイル名:BookShelf.java

public class BookShelf implements Aggregate {

// ==========================================
// =========集合体の振る舞いを記述==============
//
// これは一例なので実際、使うときは必要に応じて書く。
//
// この例では、本の取得、本の追加、本のサイズが記述。
//
// ==========================================

    // 集合体の中身はBook
    private Book[] books;

    // 集合体の最後尾の保持用
    private int last = 0;

   /*
   具体的な集合体のコンストラクタ
   引数にはMAXサイズを指定
    */
    public BookShelf(int maxsize) {
        // MAXサイズのBookクラスをインスタンス化する(コンポジション)
        this.books = new Book[maxsize];
    }

    /*
     Bookのゲッター
     引数には取得したいindexを指定
     返却値はBookを戻す
     */
    public Book getBookAt(int index) {
        // 指定されたindexのBookを返却
        return books[index];
    }

    /*
      Bookのアペンド
      引数には追加したいBookを指定
     */
    public void appendBook(Book book) {
        // 指定されたBookを最後尾に追加
        this.books[last] = book;
        // 最後尾をインクリメント
        last++;
    }
    /*
     Bookのサイズを返す
     */
    public int getLength() {
        // 最後尾の値を返却
        return last;
    }

// ==========================================
// ここまで本の集合体の振る舞いに必要な処理。
// 使うときはここまでのメソッドでいろいろ設定してから
// 反復子にアップキャストして返却させる。(Main.java参照)
// ==========================================
    public Iterator iterator() {// 適切なIteratorを返す
        // BookShelfIteratorはIteratorを継承してるのでアップキャストできる
        return new BookShelfIterator(this); //ConcreteIteratorオブジェクトの返却
    }
}
--------------------------------------------------------------------------
集合体の反復子

ファイル名: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;
    }
}
----------------------------------------------------------------------
メインクラスからの使い方

ファイル名:Main.java
import java.util.*;

public class Main {
    public static void main(String[] args) {

// ==== (集合体の設定)================
        // 集合体にサイズを指定して生成
        BookShelf bookShelf = new BookShelf(4);

        // 集合体にBookを追加
        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());
        }

// ================================
    }
}

------------------------
大事なのは
ConcreateIteratorは、iterator()メソッドにより適切なiteratorを返却できること。
ConcreateAggregateは、集合体のどこを操作しているか正しく記録できること。
そうすれば、
 ある集合体の要素1つ1つに、順次アクセスする事ができるようですね。

0 件のコメント:

コメントを投稿









ロリポップ!なら月々105円から

WordPress、MovableTypeなどの簡単インストール、

アクセス解析、ウェブメーラーが標準装備!






プロペシア