当前位置: 首页 > news >正文

设计模式(十五):Iterator迭代器模式 -- 行为型模式

1.概述

类中的面向对象编程封装应用逻辑。类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态。单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合。

集合不一定是均一的。图形用户界面框架中的 Window 对象可以收集任意数量的控制对象 - Menu、Slider 和 Button。并且,集合的实现可以有多种方式:PHP 数字是一个集合,但也是一个散列表,一个链接列表,一个堆栈以及队列。

例子1:电视遥控器的频道遍历

2.问题

 

如何操纵任意的对象集合? 
如一个列表(List)或者一个集合(Set),我们又如何提供一种方法来让别人可以访问它的元素,而又不需要暴露它的内部结构?

 

3.解决方案

迭代器模式:使用迭代器模式来提供对聚合对象的统一存取,即提供一个外部的迭代器来对聚合对象进行访问和遍历 , 而又不需暴露该对象的内部结构。又叫做游标(Cursor)模式 。
你可能没有意识到这一点,但你每天都在使用迭代器模式 。
如在PHP开发中,它潜藏在 PHP 的数组类型和各种数组操作函数中。(其实,给你一些固有类的数组的组合和一群用这些固有类工作的可变函数,你将不得不使用这些数组来处理对象集合。这是在 PHP 中的本地数组迭代:

 

  1. $test  =  array(‘one’,  ‘two’,  ‘three’);  
  2. $output  =  ‘’; reset($test);   
  3. do  {  
  4. $output  .=  current($test);  
  5. }  while  (next($test));  
  6. echo  $output;  //  produces  ‘onetwothree’  

 

 

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

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

 

4.适用性

迭代器模式可用来:

• 访问一个聚合对象的内容而无需暴露它的内部表示。
• 需要为聚合对象提供多种遍历方式。
• 为遍历不同的聚合结构提供一个统一的接口 (即, 支持多态迭代)

5.结构

结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符号“单一职责原则”。

注意,在迭代器模式中,具体迭代器角色和具体容器角色是耦合在一起的——遍历算法是与容器的内部细节紧密相关的。为了使客户程序从与具体迭代器角色耦合的困境中脱离出来,避免具体迭代器角色的更换给客户程序带来的修改,迭代器模式抽象了具体迭代器角色,使得客户程序更具一般性和重用性。这被称为多态迭代

6.模式的组成

抽象迭代器(Iterator): 迭代器定义访问和遍历元素的接口。
具体迭代器(ConcreteIterator):  具体迭代器实现迭代器Iterator接口。对该聚合遍历时跟踪当前位置。
抽象聚合类(Aggregate): 聚合定义创建相应迭代器对象的接口。
具体聚合类(ConcreteAggregate): 体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。

7.效果

 

•迭代器模式的作用:
1 ) 它支持以不同的方式遍历一个聚合对象 : 复杂的聚合可用多种方式进行遍历。迭代器模式使得改变遍历算法变得很容易 : 仅需用一个不同的迭代器的实例代替原先的实例即可。你也可以自己定义迭代器的子类以支持新的遍历。
2) 迭代器简化了聚合的接口 有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了。这样就简化了聚合的接口。
3) 在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。
4)在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。
迭代器模式的缺点
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

 

8.实现

 

我们直接实现spl的iterator:

 

  1. <?php  
  2.   
  3. /** 
  4.  * 具体迭代器(ConcreteIterator):  具体迭代器实现迭代器Iterator接口。对该聚合遍历时跟踪当前位置。 
  5.  */  
  6. class  ConcreteIterator implements  Iterator {  
  7.     protected $_key;  
  8.     protected $_collection;  
  9.     public function __construct($collection){  
  10.         $this->_collection = $collection;  
  11.         $this->_key = 0;  
  12.     }  
  13.     public function rewind(){  
  14.         $this->_key = 0;  
  15.     }  
  16.     public function valid(){  
  17.   
  18.         return isset($this->_collection[$this->_key]);  
  19.     }  
  20.     public function key(){  
  21.         return $this->_key;  
  22.     }  
  23.     public function current(){  
  24.         return $this->_collection[$this->_key];  
  25.     }  
  26.     public function next(){  
  27.         return ++$this->_key;  
  28.     }  
  29.   
  30. }  
  31.   
  32. /** 
  33.  * 具体聚合类(ConcreteAggregate):  
  34.  */  
  35. class ConcreteAggregate implements IteratorAggregate{  
  36.     protected $_arr;  
  37.     public function __construct($array){  
  38.         $this->_arr = $array;  
  39.     }  
  40.   
  41.     public function getIterator(){  
  42.         return new    ConcreteIterator($this->_arr);  
  43.     }  
  44. }  
  45.   
  46. $_collectionay = array(1,2,3,3,4);  
  47. $it = new ConcreteIterator($_collectionay);  
  48. foreach($it as $key=>$value){  
  49.     echo $key.':'.$value.'<br/>';  
  50. }  


 

 

9.与其他相关模式

Composite :迭代器常被应用到象复合这样的递归结构上。
Factory Method:多态迭代器靠Factory Method来例化适当的迭代器子类。
Memento:常与迭代器模式一起使用。迭代器可使用一个 Memento来捕获一个迭代的状态。迭代器在其内部存储Memento。

10.总结与分析

 

 

1)聚合是一个管理和组织数据对象的数据结构。
2)聚合对象主要拥有两个职责:一是存储内部数据;二是遍历内部数据。
3)存储数据是聚合对象最基本的职责。
4)将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。
 
 本文转自二郎三郎博客园博客,原文链接:http://www.cnblogs.com/haore147/p/3888154.html,如需转载请自行联系原作者

相关文章:

  • mysql搭建主从数据库及测试(ubuntu)
  • python 输入 和文件操作
  • Jupyter Notebook远程服务器配置[转]
  • 使用Nginx负载均衡搭建高性能.NETweb应用程序(转)
  • MySQL索引的使用方式和缺点
  • PHP在Windows IIS上传的图片无法访问的解决方法
  • LINUX系统安装MYSQL命令
  • Jmeter简单应用7
  • 【转】UNREFERENCED_PARAMETER的作用
  • Bootstrap框架下实现图片切换
  • SpringBoot学习之路:02.第一个程序Hello World及项目结构介绍
  • samba部署和优化
  • OSChina 周日乱弹 ——花季少女突然离开,昨夜他们做了什么?
  • VC++开发(一)——VC++自定义注释
  • 一个典型核心网络故障分析
  • 网络传输文件的问题
  • 【Amaple教程】5. 插件
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • 2017-08-04 前端日报
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Bootstrap JS插件Alert源码分析
  • canvas 五子棋游戏
  • Git 使用集
  • GitUp, 你不可错过的秀外慧中的git工具
  • Invalidate和postInvalidate的区别
  • JavaScript 基础知识 - 入门篇(一)
  • MySQL-事务管理(基础)
  • python docx文档转html页面
  • Python打包系统简单入门
  • springboot_database项目介绍
  • SwizzleMethod 黑魔法
  • VUE es6技巧写法(持续更新中~~~)
  • Vue 重置组件到初始状态
  • WePY 在小程序性能调优上做出的探究
  • 技术发展面试
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 嵌入式文件系统
  • 说说动画卡顿的解决方案
  • 用element的upload组件实现多图片上传和压缩
  • 自定义函数
  • 《天龙八部3D》Unity技术方案揭秘
  • Spring Batch JSON 支持
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (转)http-server应用
  • ./和../以及/和~之间的区别
  • .md即markdown文件的基本常用编写语法
  • .net core 6 redis操作类
  • .NET DataGridView数据绑定说明
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NetCore 如何动态路由
  • .NET成年了,然后呢?