PHP7でデザインパターン入門1/23 Iteratorパターン

結城浩氏の「増補改訂版Java言語で学ぶデザインパターン入門」を読んでいる。 これは、デザインパターンについてまとめられた良書だ。

デザインパターンについて、自分なりまとめてみようと思う。

Iterator パターンとは

Iteratorパターンとは、何かの集合体を順番に指し示して、全体をスキャンする処理を行うためのパターンである。

Iterator パターン - Wikipedia

Iterator pattern - Wikipedia

example

Iteratorパターンを利用して、本棚に本を入れ、その本の名前を順番に表示するプログラムを作成する。 PHP7で実装してみる。

<?php
interface Aggregate
{
    public function iterator(): MyIterator;
}

interface MyIterator
{
    public function hasNext(): bool;
    public function next();
}

class Book
{
    private $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    public function getName(): string {
        return $this->name;
    }
}

class BookShelf implements Aggregate
{
    private $books;
    private $last = 0;

    public function getBookAt(int $index): Book {
        return $this->books[$index];
    }

    public function appendBook(Book $book) {
        $this->books[$this->last] = $book;
        $this->last++;
    }

    public function getLength(): int {
        return $this->last;
    }

    public function iterator(): MyIterator {
        return new BookShelfIterator($this);
    }
}

class BookShelfIterator implements MyIterator {
    private $bookShelf;
    private $index;

    public function __construct(BookShelf $bookShelf) {
        $this->bookShelf = $bookShelf;
        $this->index = 0;
    }

    public function hasNext(): bool {
        return ($this->index < $this->bookShelf->getLength()) ? true : false;
    }

    public function next() {
        $book = $this->bookShelf->getBookAt($this->index);
        $this->index++;
        return $book;
    }
}

上記のiteratorパターンは以下のように利用できる

<?php
$bookShelf = new BookShelf();
$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"));
$it = $bookShelf->iterator();
while ($it->hasNext()) {
    $book = $it->next();
    echo $book->getName() . PHP_EOL;
}

実行結果

Around the World in 80 Days
Bible
Cinderella
Daddy-Long-Legs

まとめ

Iteratorを使うことで、BookShelfの実装に依存せずに数え上げることができる。 つまり、BookSelfの修正はwhile内のループには影響しない。BookSelfの利用者は、本の管理方法が変わったとしても、同じように数え上げることができる。

関連パターン

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門