初识设计模式——迭代器模式(PHP中迭代器(Iterator)的使用)

初始迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。在《大话设计模式》中提到,此设计模式实用价值远不如学习价值大了,martin flower甚至提出撤销此设计模式。另外,无论是JAVA、Python,亦或是PHP中,都存在多种多样的遍历聚合元素的方式,所以此处就不过多的去了解了。这里我主要记录的是自己对PHP迭代器Iterator的抽象类的使用。

PHP中的迭代器

PHP中的迭代器有好几种,但是初始接口都是“iterable”,另外,由于PHP中的迭代器众多,我得精力有限,不可能学习所有的迭代器,以后有需要再补充。主要学习了几个主要的。另外,这里记录一下我知道的迭代器的类名。

Iterator::class;
IteratorIterator::class;
IteratorAggregate::class;
ArrayIterator::class;
APCIterator::class;
APCUIterator::class;
AppendIterator::class;
CachingIterator::class;
CallbackFilterIterator::class;
DirectoryIterator::class;
EmptyIterator::class;
FilesystemIterator::class;
FilterIterator::class;
GlobIterator::class;
ImagickPixelIterator::class;
InfiniteIterator::class;
IntlBreakIterator::class;
IntlCodePointBreakIterator::class;
IntlIterator::class;
IntlRuleBasedBreakIterator::class;
LimitIterator::class;
MultipleIterator::class;
NoRewindIterator::class;
OuterIterator::class;
ParentIterator::class;
RecursiveArrayIterator::class;
RecursiveCachingIterator::class;
RecursiveCallbackFilterIterator::class;
RecursiveDirectoryIterator::class;
RecursiveFilterIterator::class;
RecursiveIterator::class;
RecursiveRegexIterator::class;
RecursiveTreeIterator::class;
RegexIterator::class;
SeekableIterator::class;
SimpleXMLIterator::class;
RecursiveIteratorIterator::class;

    Iterator(普通迭代器)

Iterator属于PHP中最简单的迭代器,实现的方法也很简单,只需要实现Iterator接口中存在的5个抽象方法即可。代码如下:

<?php
class Iterator01 implements Iterator
{
    private $data;
    private $position = 0;

    public function __construct($data, $position = 0)
    {
        $this->data = $data;
        $this->position = $position;
    }
    public function current()
    {
        if ($this->valid()) {
            return $this->data[$this->position];
        }
        return null;
    }
    public function key()
    {
        return $this->position;
    }
    public function next()
    {
        $this->position++;
        if ($this->valid()) {
            return $this->current();
        }
        return null;
    }
    public function rewind()
    {
        return $this->position = 0;
    }
    public function valid()
    {
        return $this->position>=0 && $this->position<count($this->data);
    }
}
$array = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$iterator = new Iterator01($array);
echo $iterator->current();
for ($i=0; $i<100; $i++) {
    echo $iterator->next();
}

    IteratorIterator(迭代“迭代器”)

IteratorIterator在网上的资料比较少,看手册又看不懂。简单的记录一下学习到的吧。IteratorIterator主要作用是用来迭代迭代器的。它可以通过控制InnerIterator来实现不同的逻辑操作。上代码:

<?php
//Iterator
class MyIterator implements Iterator
{
    public function valid()
    {
        echo __METHOD__ . '<br/>';
        return false;
    }
    public function rewind()
    {
        echo __METHOD__ . '<br/>';
    }
    public function next()
    {
        echo __METHOD__ . '<br/>';
    }
    public function key()
    {
        echo __METHOD__ . '<br/>';
    }
    public function current()
    {
        echo __METHOD__ . '<br/>';
    }
}
//IteratorIterator
class MyIteratorIterator extends IteratorIterator
{
    public function getInnerIterator()
    {
        parent::getInnerIterator();
    }
    public function current()
    {
        echo __METHOD__ . '<br/>';
        parent::current();
    }
    public function key()
    {
        echo __METHOD__ . '<br/>';
        parent::key();
    }
    public function next()
    {
        echo __METHOD__ . '<br/>';
        parent::next();
    }
    public function rewind()
    {
        echo __METHOD__ . '<br/>';
        parent::rewind();
    }
    public function valid()
    {
        echo __METHOD__ . '<br/>';
        parent::valid();
    }
}
$arr = ['A' => 'AA', 'B' => 'BB', 'C' => 'CC', 'D' => 'DD', 'E' => 'EE', 'F' => 'FF', 'G' => 'GG'];
$myIterator = new MyIterator($arr);


$myIteratorIterator = new MyIteratorIterator(new MyIterator($arr));
echo '当前调用的是current方法:<br/>';
$myIteratorIterator->current();
echo '<hr/>';
echo '当前调用的是next方法:<br/>';
$myIteratorIterator->next();
echo '<hr/>';
echo '当前调用的是key方法:<br/>';
$myIteratorIterator->key();
echo '<hr/>';
echo '当前调用的是valid方法:<br/>';
$myIteratorIterator->valid();
echo '<hr/>';
echo '当前调用的是rewind方法:<br/>';
$myIteratorIterator->rewind();
echo '<hr/>';

上述方法只可以迭代显示以连续数字为key的数组:

如果MyIterator中的valid返回的是false,则返回结果为:

最后总结如下:IteratorIterator在调用next、rewind这两个移动指针的方法时,会主动的调用参数迭代器(我得例子中是MyIterator),调用的顺序为:

(1) IteratorIterator::next-->InnerIterator::next-->InnerIterator::valid(返回值为false)

(2) IteratorIterator::next-->InnerIterator::next-->InnerIterator::valid(返回值为true)-->InnerIterator::current-->InnerIterator::key

(1) IteratorIterator::rewind-->InnerIterator::next-->InnerIterator::valid(返回值为false)

(1) IteratorIterator::rewind-->InnerIterator::next-->InnerIterator::valid(返回值为false)-->InnerIterator::current-->InnerIterator::key

在网上找资料的时候看到了一个大神的博客,关于IteratorIterator的,地址:https://blog.csdn.net/hxx_yang/article/details/82915634。先把大神的结果粘在这里,防止博客牵走。

Outer的每次迭代会先调用自己的方法,然后转发给Inner。
Outer内部方法的返回值都是基于Inner的相对于方法的返回。
你可以在Outer内方法对Inner的返回值做逻辑处理。
当Inner的valid返回false的时候,外层的Outer也将停止迭代。
Outer内的方法对返回值的修改并不会影响Inner。
Outer内的方法在迭代过程中并不会执行getInnerIterator方法,它只是一个获取Inner方法的调用接口。

    ArrayIterator(数组迭代器)

最后介绍一个数组迭代器,类似于next()、current()等一系列的指针函数,也可以用来遍历数据。

<?php
$arr = ['A' => 'AA', 'B' => 'BB', 'C' => 'CC', 'D' => 'DD', 'E' => 'EE', 'F' => 'FF', 'G' => 'GG'];
$arrIterator = new ArrayIterator($arr);

while ($arrIterator->valid()) {
    echo $arrIterator->current();
    $arrIterator->next();
    echo '<br/>';
}

var_dump(iterator_to_array($arrIterator));

鸣谢

非常感谢此CSDN博主的文章,让我学到了不少,地址附上了https://blog.csdn.net/hxx_yang/article/details/82915634

参考资料

  1. https://blog.csdn.net/hxx_yang/article/details/82915634
  2. 《大话设计模式》
  3. 《菜鸟教程——迭代器模式》

下一篇

初识设计模式——单例模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值