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


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类图

1107940-8c8efff9876e388d.png

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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值