PHP设计模式-迭代器模式

引言:在理解迭代器模式之前,先了解一下迭代器的概念。迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器的内容。

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。

概念:迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

迭代器模式的关键思想是:将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(Iterator)中。

我们可能没有注意到,我们每天都在使用迭代器模式。在PHP开发中,它潜藏在PHP数组类型和各种数组操作类型中。比如在PHP中的本地数组迭代:

<?php
$arr = array('one','two','three');
$output = '';
reset($arr);
do{
  $output .= current($arr)."<br/>";
} while(next($arr));
echo $output;

  reset()函数将迭代重新转到数组的开始,current()返回当前元素的值,next()则前进至数组中的下一个元素并返回新的current()值,当你超出数组的最后一个元素时,next()返回false,使用这些迭代方法,PHP数组的内部实现就与你不相关了。

  迭代器结合了封装和多态的面向对象设计原理。使用迭代器,可以对集合中的对象进行操作,而无需专门了解集合如何显现或者集合包含什么(对象的种类)。迭代器提供了不同固定迭代实现的统一接口,完全包含了如何操纵特定集合的详细信息,包括显示哪些项(过滤)及其显示顺序(排序)。

适用性:

  • 访问一个聚合对象的内容而无需暴露它的内部细节。
  • 需要为聚合对象提供多种遍历方式。支持以不同的遍历一个聚合对象,复杂的聚合可用多种方式进行遍历,迭代器模式使得改变遍历算法变得更容易,仅需要用一个不同的迭代器的实例代替原先的实例即可。你也可以自己定义迭代器的子类以支持新的遍历。
  • 为遍历不同的聚合结构提供一个统一的接口。(即支持多态迭代)。迭代器简化了聚合的接口,有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了。
  • 在统一格局和上可以有多个遍历,每个迭代器保持自己的遍历状态,因此可以同时进行多个遍历。
  • 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无需修改原有代码,符合“开闭原则”(软件系统中包含的各种组件,例如模块(Modules)、(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,引入新功能。开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭”,是指对于原有代码的修改是封闭的,即修改原有的代码对外部的使用是透明的。)。

角色:

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

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

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

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

 

代码示例:

\Libs\Aggregate.php

<?php
namespace Libs;

abstract class Aggregate
{
    protected $_objs;
    protected $_size;

    public function createIterator()
    {
        
    }
    public function getItem()
    {
        
    }
    public function getSize()
    {
        return $this->_size;
    }
}

\Libs\ConcreteAggregate.php

<?php
namespace Libs;

class ConcreteAggregate extends Aggregate
{
    public function __construct($count)
    {
        for($i=0;$i<$count;$i++){
            $this->_objs[] = $i;
        }
    }
    public function createIterator()
    {
        return new ConcreteIterator($this);
    }
    public function getItem($idx=0)
    {
        if($idx < $this->getSize()){
            return $this->_objs[$idx];
        } else {
            return FALSE;
        }
    }
    public function getSize()
    {
        return count($this->_objs);
    }
}

\Libs\Iterator.php

<?php
namespace Libs;

abstract class Iterator
{
    protected $_ag;
    protected $_idx;
    public function first(){}
    public function next(){}
    public function isDone(){}
    public function currentItem(){}
}

\Libs\ConcreteIteratorSort.php

<?php
namespace Libs;

class ConcreteIteratorSort extends Iterator 
{
    public function __construct($ag,$idx=0)
    {
        $this->_ag = $ag;
        $this->_idx = $idx;
    }
    public function first()
    {
        $this->_idx = 0;
    }
    public function next()
    {
        if($this->_idx < $this->_ag->getSize()){
            $this->_idx++;
        }
    }
    public function isDone()
    {
        if($this->_idx == $this->_ag->getSize()){
            return TRUE;
        } else {
            return FALSE;
        }
    }
    public function currentItem()
    {
        return $this->_ag->getItem($this->_idx);
    }
}

\Libs\ConcreteIteratorUnSort.php

<?php
namespace Libs;

class ConcreteIteratorUnSort extends Iterator 
{
    public function __construct($ag,$idx=0)
    {
        $this->_ag = $ag;
        $this->_idx = $idx;
    }
    public function first()
    {
        $this->_idx = $this->_ag->getSize()-1;
    }
    public function next()
    {
        if($this->_idx >=0){
            $this->_idx--;
        }
    }
    public function isDone()
    {
        if($this->_idx < 0){
            return TRUE;
        } else {
            return FALSE;
        }
    }
    public function currentItem()
    {
        return $this->_ag->getItem($this->_idx);
    }
}

 

\Libs\UseIterator.php

<?php
namespace Libs;

class UseIterator
{
    public static function index()
    {
        $ag = new ConcreteAggregate(10);
        $it_sort = new ConcreteIteratorSort($ag);
        $it_sort->first();
        for(;$it_sort->isDone()==FALSE;$it_sort->next())
        {
            echo $it_sort->currentItem().'***';
        }
        echo '<br/>';
        $it_unsort = new ConcreteIteratorUnSort($ag);
        $it_unsort->first();
        for(;$it_unsort->isDone()==FALSE;$it_unsort->next())
        {
            echo $it_unsort->currentItem().'***';
        }
    }
    
}

调用代码

IMooc\UseIterator::index();

结果:

0***1***2***3***4***5***6***7***8***9***
9***8***7***6***5***4***3***2***1***0***

 

 

推荐阅读>>

设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)

PHP设计模式笔记--迭代器模式(Iterator)

posted @ 2016-06-29 17:26  DDDDemo  阅读(705)  评论(0编辑  收藏  举报