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

WBOY
Release: 2016-06-20 12:41:33
Original
930 people have browsed it

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();    }}
Copy after login

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);    }}
Copy after login

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;    }}
Copy after login

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;    }}
Copy after login

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);    }}
Copy after login
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!