Php设计模式之【迭代器模式Iterator Pattern】

概述

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

案例

黑枣电视公司的在生产的电视机,使用遥控器[后一个]和[前一个]按钮调节频道。当按下[后一个]按钮时,将切换到下一个预置的频道。想象一下在陌生的城市中的旅店中看电视。当改变频道时,重要的不是几频道,而是节目内容。如果对一个频道的节目不感兴趣,那么可以换下一个频道,而不需要知道它是几频道。。

分析OOA:

迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。这里有两个方案:

方案一、可以将遍历方法塞到容器对象中去

方案二、容器不去提供什么遍历算法,让使用容器的人自己去实现去吧。

方案一中,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。方案二倒是省事又提高了容器的内聚能力。

设计OOD:

<UML>


<说明>

  1. 迭代器角色(ChanelIterator):迭代器角色负责定义访问和遍历元素的接口。
    在本例中ChanelIterator定义迭代器必须实现moveText\first\next\current方法
  2. 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
    TvChannelIterator为电视频道的具体迭代实现类,封装了具体的迭代算法。
  3. 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
    在本例中ChannelList为容器角色,定义了getIterator以使容器角色取得一个具体迭代器角色实例。
  4. 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。
    在本例中TvChannellist为具体容器角色

编程 OOP:

<代码>

//迭代器角色(Iterator)
interface ChannelIterator
{
    /**
     * 判断可否向下移动游标
     * @abstract
     * @return boolean
     */
    public function moveNext();

    /**
     * 将游标置0
     * @abstract
     * @return none
     */
    public function first();

    /**
     * 向前移动游标
     * @abstract
     * @return none
     */
    public function next();

    /**
     * 取得当前游标所指数据项
     * @abstract
     * @return none
     */
    public function current();
}

//具体迭代器角色(Concrete Iterator)
class TvChannelIterator implements ChannelIterator
{
    private $list = null;
    private $index = 0;
    public function __construct($list){
        $this->list = $list;
        $index = 0;
    }
    public function moveNext()
    {
        if($this->index < count($this->list)){
            return true;
        }else{
            return false;
        }
    }

    public function first()
    {
       $this->index = 0;
    }

    public function next()
    {
       if( $this->index < count($this->list)) $this->index++;
    }

    public function current()
    {
        return $this->list[$this->index];
    }
}
//容器角色(Container)
interface ChannelList
{
    /**
     * 取得一个具体迭代器角色实例
     * @abstract
     * @return mixed 具体迭代器角色实例
     */
    public function getIterator();
}

//具体容器角色(Concrete Container)
class TvChannellist implements ChannelList
{
    private $list;

    public function __construct()
    {
        $this->list = array(
            '0' => '北京台',
            '1' => '山东台',
            '2' => '湖南台',
            '3' => '凤凰台',
            '4' => '河北台'
        );
    }

    public function getIterator()
    {
        return new TvChannelIterator($this->list);
    }

    public function getLength()
    {
        return count($this->list);
    }

    public function getChannel($index = 0)
    {
        return $this->list[$index];
    }
}


测试用例Test Case:

<代码>

class testDriver
{
    public function run()
    {
        $channels = new TvChannellist();
        $iterator = $channels->getIterator();
        while($iterator->moveNext()){
            echo "频道:". $iterator->current()."\n";
            $iterator->next();
        }
    }
}

$test = new testDriver();
$test->run();

<输出>


小结:

面向对象设计原则中有一条是类的单一职责原则,所以我们要尽可能的去分解这些职责,用不同的类去承担不同的职责。Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。

【常用情境】:

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

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

3.为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

【优点】

支持以不同的方式遍历一个容器角色。根据实现方式的不同,效果上会有差别。

2. 简化了容器的接口。

3. 对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。

【缺点 】

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

将容器的内部细节向迭代器暴露无遗

*********************转载请注明来源********************

* 作者:叶文涛 

* 标题:Php设计模式之迭代器模式Iterator Pattern(一)

* 参考:

*《Head First设计模式》Eric Freeman等著

*《PHP设计模式》Aaron Saray等著,梁志敏等译(PS:翻译的是狗屁水平)

*  Java设计模式之迭代器模式 http://www.51cto.com/specbook/11/9578.htm

*  .NET设计模式(18):迭代器模式(Iterator Pattern)http://www.cnblogs.com/Terrylee/archive/2006/09/16/Iterator_Pattern.html

*********************转载请注明来源********************


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值