Iteratorパターン

  • 14
    Like
  • 0
    Comment
More than 1 year has passed since last update.

概要

デザインパターンのIteratorパターンの練習用の実装とそれに関することをまとめてみたものです。

サンプル

本棚(BookShelfクラス)に本(Bookクラス)を格納し、Iteratorクラスを使い本棚に格納された本の情報を順番に表示する。

Aggregate.java
public interface Aggregate {
    public Iterator orderIterator();
    public Iterator reverseIterator();
}
Iterator.java
public interface Iterator {
    public boolean hasNext();
    public Object next();
}
BookShelf.java
public class BookShelf implements Aggregate {
    private List<Book> _books = new ArrayList<Book>();

    public void addBook(Book book) {
        _books.add(book);
    }

    public Book getBookAt(int idx) throws IndexOutOfBoundsException {
        return _books.get(idx);
    }

    public void removeBookAt(int idx) throws IndexOutOfBoundsException {
         _books.remove(idx);
    }

    public int getNumberOfBooks() {
        return _books.size();
    }

    @Override
    public Iterator orderIterator() {
        return new OrderIterator(this);
    }

    @Override
    public Iterator reverseIterator() {
        return new ReverseIterator(this);
    }
}
Book.java
public class Book {
    private int _bookId;
    private String _bookTitle;

    public Book(int bookId, String bookTitle) {
        _bookId = bookId;
        _bookTitle = bookTitle;
    }

    public int getId() {
        return _bookId;
    }

    public String getTitle() {
        return _bookTitle;
    }
}
OrderIterator.java
public class OrderIterator implements Iterator {

    private BookShelf _baseObj;
    private int _index = 0;

    public OrderIterator(BookShelf bookShelf) {
        _baseObj = bookShelf;
    }

    @Override
    public boolean hasNext() {
        try {
            _baseObj.getBookAt(_index);
            return true;
        } catch (IndexOutOfBoundsException ex) {
            return false;
        }
    }

    @Override
    public Object next() {
        Book book = _baseObj.getBookAt(_index);
        _index++;
        return book;
    }
}
ReverseIterator.java
public class ReverseIterator implements Iterator {

    private BookShelf _baseObj;
    private int _index;

    public ReverseIterator(BookShelf bookShelf) {
        _baseObj = bookShelf;
        _index = _baseObj.getNumberOfBooks() - 1;
    }

    @Override
    public boolean hasNext() {
        try {
            _baseObj.getBookAt(_index);
            return true;
        } catch (IndexOutOfBoundsException ex) {
            return false;
        }
    }

    @Override
    public Object next() {
        Book book = _baseObj.getBookAt(_index);
        _index--;
        return book;
    }
}

インタフェース Aggregateクラス, Iteratorクラス。
具体的なクラスとして BookShelf, Book, (順番表示用)OrderIterator, (逆順表示用)ReverIteratorクラスを準備。

そんで、メインクラスで実行します。

Main.java
public class Main {
    public static void main(String args[]) {
        BookShelf bookShelf = new BookShelf();

        bookShelf.addBook(new Book(1, "English"));
        bookShelf.addBook(new Book(2, "Math"));
        bookShelf.addBook(new Book(3, "History"));
        bookShelf.addBook(new Book(4, "Physics"));
        bookShelf.addBook(new Book(5, "Programming"));
        bookShelf.addBook(new Book(6, "Science"));

        System.out.println("------- Order -------");
        Iterator orderIt = bookShelf.orderIterator();
        while (orderIt.hasNext()) {
            Book book = (Book) orderIt.next();
            System.out.println("id: "+book.getId()+" title: "+book.getTitle());
        }

        System.out.println("------- Reverse Order -------");
        Iterator reverseIt = bookShelf.reverseIterator();
        while (reverseIt.hasNext()) {
            Book book = (Book) reverseIt.next();
            System.out.println("id: "+book.getId()+" title: "+book.getTitle());
        }
    }
}
Result
------- Order -------
id: 1 title: English
id: 2 title: Math
id: 3 title: History
id: 4 title: Physics
id: 5 title: Programming
id: 6 title: Science
------- Reverse Order -------
id: 6 title: Science
id: 5 title: Programming
id: 4 title: Physics
id: 3 title: History
id: 2 title: Math
id: 1 title: English

まとめ

・数え上げのロジックの実装を切り離すことで、Iteratorを使って順番に表示している側は、数え上げのロジックに変更があっても修正する必要が無い。
・積極的に抽象クラスやインタフェースを使うことはクラス間の結合度に大きく関わる。
・様々な数え上げのIteratorを提供できる。今回は順番に、逆順に操作を行うIteratorを実装してみた。