PHP 设计模式系列 -- 迭代器模式(Iterator)

WBOY
發布: 2016-06-20 12:41:33
原創
956 人瀏覽過

1、模式定义

迭代器模式 (Iterator),又叫做游标(Cursor)模式。提供一种方法访问一个容器(Container)对象中各个元素,而又不需暴露该对象的内部细节。

当你需要访问一个聚合对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。另外,当需要对聚集有多种方式遍历时,可以考虑去使用迭代器模式。迭代器模式为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。

PHP标准库(SPL)中提供了迭代器接口 Iterator,要实现迭代器模式,实现该接口即可。

2、UML类图

3、示例代码

Book.php

<?phpnamespace DesignPatterns\Behavioral\Iterator;class Book{    private $author;    private $title;    public function __construct($title, $author)    {        $this->author = $author;        $this->title = $title;    }    public function getAuthor()    {        return $this->author;    }    public function getTitle()    {        return $this->title;    }    public function getAuthorAndTitle()    {        return $this->getTitle() . ' by ' . $this->getAuthor();    }}
登入後複製

BookList.php

<?phpnamespace DesignPatterns\Behavioral\Iterator;class BookList implements \Countable{    private $books;    public function getBook($bookNumberToGet)    {        if (isset($this->books[$bookNumberToGet])) {            return $this->books[$bookNumberToGet];        }        return null;    }    public function addBook(Book $book)    {        $this->books[] = $book;    }    public function removeBook(Book $bookToRemove)    {        foreach ($this->books as $key => $book) {            /** @var Book $book */            if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {                unset($this->books[$key]);            }        }    }    public function count()    {        return count($this->books);    }}
登入後複製

BookListIterator.php

<?phpnamespace DesignPatterns\Behavioral\Iterator;class BookListIterator implements \Iterator{    /**     * @var BookList     */    private $bookList;    /**     * @var int     */    protected $currentBook = 0;    public function __construct(BookList $bookList)    {        $this->bookList = $bookList;    }    /**     * Return the current book     * @link http://php.net/manual/en/iterator.current.php     * @return Book Can return any type.     */    public function current()    {        return $this->bookList->getBook($this->currentBook);    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Move forward to next element     * @link http://php.net/manual/en/iterator.next.php     * @return void Any returned value is ignored.     */    public function next()    {        $this->currentBook++;    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Return the key of the current element     * @link http://php.net/manual/en/iterator.key.php     * @return mixed scalar on success, or null on failure.     */    public function key()    {        return $this->currentBook;    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Checks if current position is valid     * @link http://php.net/manual/en/iterator.valid.php     * @return boolean The return value will be casted to boolean and then evaluated.     *       Returns true on success or false on failure.     */    public function valid()    {        return null !== $this->bookList->getBook($this->currentBook);    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Rewind the Iterator to the first element     * @link http://php.net/manual/en/iterator.rewind.php     * @return void Any returned value is ignored.     */    public function rewind()    {        $this->currentBook = 0;    }}
登入後複製

BookListReverseIterator.php

<?phpnamespace DesignPatterns\Behavioral\Iterator;class BookListReverseIterator implements \Iterator{    /**     * @var BookList     */    private $bookList;    /**     * @var int     */    protected $currentBook = 0;    public function __construct(BookList $bookList)    {        $this->bookList = $bookList;        $this->currentBook = $this->bookList->count() - 1;    }    /**     * Return the current book     * @link http://php.net/manual/en/iterator.current.php     * @return Book Can return any type.     */    public function current()    {        return $this->bookList->getBook($this->currentBook);    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Move forward to next element     * @link http://php.net/manual/en/iterator.next.php     * @return void Any returned value is ignored.     */    public function next()    {        $this->currentBook--;    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Return the key of the current element     * @link http://php.net/manual/en/iterator.key.php     * @return mixed scalar on success, or null on failure.     */    public function key()    {        return $this->currentBook;    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Checks if current position is valid     * @link http://php.net/manual/en/iterator.valid.php     * @return boolean The return value will be casted to boolean and then evaluated.     *       Returns true on success or false on failure.     */    public function valid()    {        return null !== $this->bookList->getBook($this->currentBook);    }    /**     * (PHP 5 >= 5.0.0)<br/>     * Rewind the Iterator to the first element     * @link http://php.net/manual/en/iterator.rewind.php     * @return void Any returned value is ignored.     */    public function rewind()    {        $this->currentBook = $this->bookList->count() - 1;    }}
登入後複製

4、测试代码

Tests/IteratorTest.php

<?phpnamespace DesignPatterns\Behavioral\Iterator\Tests;use DesignPatterns\Behavioral\Iterator\Book;use DesignPatterns\Behavioral\Iterator\BookList;use DesignPatterns\Behavioral\Iterator\BookListIterator;use DesignPatterns\Behavioral\Iterator\BookListReverseIterator;class IteratorTest extends \PHPUnit_Framework_TestCase{    /**     * @var BookList     */    protected $bookList;    protected function setUp()    {        $this->bookList = new BookList();        $this->bookList->addBook(new Book('Learning PHP Design Patterns', 'William Sanders'));        $this->bookList->addBook(new Book('Professional Php Design Patterns', 'Aaron Saray'));        $this->bookList->addBook(new Book('Clean Code', 'Robert C. Martin'));    }    public function expectedAuthors()    {        return array(            array(                array(                    'Learning PHP Design Patterns by William Sanders',                    'Professional Php Design Patterns by Aaron Saray',                    'Clean Code by Robert C. Martin'                )            ),        );    }    /**     * @dataProvider expectedAuthors     */    public function testUseAIteratorAndValidateAuthors($expected)    {        $iterator = new BookListIterator($this->bookList);        while ($iterator->valid()) {            $expectedBook = array_shift($expected);            $this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());            $iterator->next();        }    }    /**     * @dataProvider expectedAuthors     */    public function testUseAReverseIteratorAndValidateAuthors($expected)    {        $iterator = new BookListReverseIterator($this->bookList);        while ($iterator->valid()) {            $expectedBook = array_pop($expected);            $this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());            $iterator->next();        }    }    /**     * Test BookList Remove     */    public function testBookRemove()    {        $this->bookList->removeBook($this->bookList->getBook(0));        $this->assertEquals($this->bookList->count(), 2);    }}
登入後複製
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!