php设计模式(十七):迭代器模式(Iterator)

2023-05-19 10:13:31 浏览数 (2)

迭代器模式

迭代器模式又称为:Iterator。迭代器是一种行为设计模式,能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。迭代器模式允许用户通过特定的顺序访问容器中的数据,它将数据和顺序的实现分离,很少有有人直接去用迭代器的了,因为一般语言已经帮实现了如:foreach…,所以单独使用的常见很少了。

问题

需要对数组进行倒序遍历怎么办?

解决方法

前面也说了很多语言已经实现了迭代器,那迭代器是是不是没有用武之地了?其实不然,大部分语言只提供了正序遍历(使用迭代器),在特定场景下是要用到迭代器的,如:对一个数组需要特定(倒序、按元素大小)遍历、对图(深度、广度)遍历等。我们可以使用迭代器模式,对数据进行倒序遍历,语言中 foreach 也是迭代器进行了正序遍历而已。

结构

IterableCollection: 容器接口 定义获取迭代器的方法 ; ConcreteCollection : 实现 IterableCollection 接口的具体容器类 ; Iterator: 迭代器接口 这里定义了 hasMore 和 getNext 方法 ; Concretelterator: 实现 Iterator 接口的具体迭代器类 ;

代码示例

容器接口

代码语言:javascript复制
/**
 * 容器接口
 */
interface IterableCollection
{
    /**
     * 创建迭代器
     * @return mixed
     * @author chendashengpc
     */
    public function createIterator();
}

具体容器类

代码语言:javascript复制
/**
 * 具体容器类
 */
class ConcreteCollection implements IterableCollection
{
    public $collection;

    public function add($value)
    {
        $this->collection[] = $value;
    }

    public function createIterator()
    {
        return new Concretelterator($this->collection);
    }
}

迭代器接口

代码语言:javascript复制
/**
 * 迭代器接口类
 */
interface Iterator
{
    /**
     * 获取当前
     * @return mixed
     * @author chendashengpc
     */
    public function getCurrent();

    /**
     * 获取下一个
     * @return mixed
     * @author chendashengpc
     */
    public function getNext();

    /**
     * 是否还有更多
     * @return bool
     * @author chendashengpc
     */
    public function hasMore(): bool;
}

具体迭代器类

代码语言:javascript复制
/**
 * 具体迭代器(倒序迭代器)
 */
class Concretelterator implements Iterator
{
    public $collection;
    /**
     * 索引数
     * @var
     */
    private int $index;

    public function __construct(array $collection)
    {
        $this->collection = $collection;
        $this->index = count($this->collection) - 1;
    }

    public function getCurrent()
    {
        if (isset($this->collection[$this->index])) {
            return $this->collection[$this->index];
        }
        return '当前没有元素';
    }

    public function getNext()
    {
        --$this->index;
        if ($this->hasMore()) {
            return $this->collection[$this->index];
        }
        return '没有元素了';
    }

    public function hasMore(): bool
    {
        if (isset($this->collection[$this->index])) {
            return true;
        }
        return false;
    }
}

客户端使用

代码语言:javascript复制
$collection = new ConcreteCollection();

$collection->add(1);
$collection->add(5);
$collection->add(6);
$collection->add(9);

$iterator = $collection->createIterator();
echo $iterator->getCurrent() . PHP_EOL;
while ($iterator->hasMore()) {
    echo $iterator->getNext() . PHP_EOL;
}

输出

代码语言:javascript复制
9
6
5
1
没有元素了

php 官方已经提供了,请参考:迭代器

UML

优缺点

优点

  • 单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,可对客户端代码和集合进行整理。
  • 开闭原则。可实现新型的集合和迭代器并将其传递给现有代码,无需修改现有代码。
  • 可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。
  • 相似的,可以暂停遍历并在需要时继续。

缺点

  • 对于某些特殊集合,使用迭代器可能比直接遍历的效率低。

0 人点赞