美文网首页
PHP设计模式(八)-迭代器模式

PHP设计模式(八)-迭代器模式

作者: EwanRenton | 来源:发表于2018-07-26 16:36 被阅读0次

    layout: post
    title: "PHP设计模式(八)-迭代器模式"
    date: 2016-06-07 12:59:44 +0800
    comments: true
    categories: [php]


    1、模式定义

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

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

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

    2、UML类图

    image

    3、实例代码

        <?php
        
        namespace 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();
            }
        }
    
        <?php
        
        namespace 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);
            }
        }
    
        <?php
        
        namespace 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)
             *
             * 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)
             *
             * 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)
             *
             * 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)
             *
             * 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;
            }
        }
    
        
        <?php
        
        namespace 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)
             *
             * 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)
             *
             * 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)
             *
             * 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)
             *
             * 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、测试代码

    <?php
    
    namespace 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设计模式(八)-迭代器模式

          本文链接:https://www.haomeiwen.com/subject/fmibmftx.html