• 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的一个适当的实例。

    代码示例:

    LibsAggregate.php

    <?php
    namespace Libs;
    
    abstract class Aggregate
    {
        protected $_objs;
        protected $_size;
    
        public function createIterator()
        {
            
        }
        public function getItem()
        {
            
        }
        public function getSize()
        {
            return $this->_size;
        }
    }

    LibsConcreteAggregate.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);
        }
    }

    LibsIterator.php

    <?php
    namespace Libs;
    
    abstract class Iterator
    {
        protected $_ag;
        protected $_idx;
        public function first(){}
        public function next(){}
        public function isDone(){}
        public function currentItem(){}
    }

    LibsConcreteIteratorSort.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);
        }
    }

    LibsConcreteIteratorUnSort.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);
        }
    }

    LibsUseIterator.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().'***';
            }
        }
        
    }

    调用代码

    IMoocUseIterator::index();

    结果:

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

    推荐阅读>>

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

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

  • 相关阅读:
    JS Array转JSON
    js数组转字符串并用,分割
    java枚举类-根据key获取value及根据value获取key
    CSS文件引入顺序
    git pull之前要先commit
    FastJson中@JSONField注解使用
    @JsonFormat与@DateTimeFormat注解的使用
    Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明
    shell脚本使用
    ubuntu12.04 安装redis
  • 原文地址:https://www.cnblogs.com/ddddemo/p/5627656.html
Copyright © 2020-2023  润新知