PHP设计模式之迭代器模式

概念

迭代器模式(Iterator),又叫做游标(Cursor)模式。提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

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

适用场景

  1. 访问一个聚合对象的内容而无需暴露它的内部表示

  2. 支持对聚合对象的多种遍历

  3. 为遍历不同的聚合结构提供一个统一的接口

UML图

《PHP设计模式之迭代器模式》

角色

  1. Iterator(迭代器):迭代器定义访问和遍历元素的接口

  2. ConcreteIterator(具体迭代器):具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置

  3. Aggregate (聚合): 聚合定义创建相应迭代器对象的接口

  4. ConcreteAggregate (具体聚合):具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例

代码

代码如下:

PHP SPL中已经提供了迭代器接口Iterator和容器接口IteatorAggragate,其源码如下:

/**
 * Interface to detect if a class is traversable using &foreach;.
 * @link http://php.net/manual/en/class.traversable.php
 */
interface Traversable {
}

/**
 * Interface to create an external Iterator.
 * @link http://php.net/manual/en/class.iteratoraggregate.php
 */
interface IteratorAggregate extends Traversable {

    /**
     * Retrieve an external iterator
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
     * @return Traversable An instance of an object implementing <b>Iterator</b> or
     * <b>Traversable</b>
     * @since 5.0.0
     */
    public function getIterator();
}

/**
 * Interface for external iterators or objects that can be iterated
 * themselves internally.
 * @link http://php.net/manual/en/class.iterator.php
 */
interface Iterator extends Traversable {

    /**
     * Return the current element
     * @link http://php.net/manual/en/iterator.current.php
     * @return mixed Can return any type.
     * @since 5.0.0
     */
    public function current();

    /**
     * Move forward to next element
     * @link http://php.net/manual/en/iterator.next.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function next();

    /**
     * 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.
     * @since 5.0.0
     */
    public function key();

    /**
     * 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.
     * @since 5.0.0
     */
    public function valid();

    /**
     * Rewind the Iterator to the first element
     * @link http://php.net/manual/en/iterator.rewind.php
     * @return void Any returned value is ignored.
     * @since 5.0.0
     */
    public function rewind();
}

这里我们直接实现上面两个接口,请看下面代码:

<?php
header('Content-type:text/html;charset=utf-8');
/**
 * 迭代器模式
 */

/**
 * Class ConcreteIterator 具体的迭代器
 */
class ConcreteIterator implements Iterator
{
    private $position = 0;
    private $array = array();

    public function __construct($array) {
        $this->array = $array;
        $this->position = 0;
    }

    function rewind() {
        $this->position = 0;
    }

    function current() {
        return $this->array[$this->position];
    }

    function key() {
        return $this->position;
    }

    function next() {
        ++$this->position;
    }

    function valid() {
        return isset($this->array[$this->position]);
    }
}

/**
 * Class MyAggregate 聚合容器
 */
class ConcreteAggregate implements IteratorAggregate
{
    public $property;

    /**
     * 添加属性
     *
     * @param $property
     */
    public function addProperty($property)
    {
        $this->property[] = $property;
    }

    public function getIterator()
    {
        return new ConcreteIterator($this->property);
    }
}

/**
 * Class Client 客户端测试
 */
class Client
{
    public static function test()
    {
        //创建一个容器
        $concreteAggregate = new ConcreteAggregate();
        // 添加属性
        $concreteAggregate->addProperty('属性1');
        // 添加属性
        $concreteAggregate->addProperty('属性2');
        //给容器创建迭代器
        $iterator = $concreteAggregate->getIterator();
        //遍历
        while($iterator->valid())
        {
            $key   = $iterator->key();
            $value = $iterator->current();
            echo '键: '.$key.' 值: '.$value.'<hr>';
            $iterator->next();
        }

    }
}

Client:: test();

运行结果:

键: 0 值: 属性1
键: 1 值: 属性2
    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000007547513
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞