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

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

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

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

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

2.问题

 

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

 

3.解决方案

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

 

[php] view plaincopy
print?
  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:

 

[php] view plaincopy
print?
  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.mzph.cn/news/294371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android之Volley 源码解析

原文来自&#xff1a;http://www.codekk.com 1. 功能介绍 1.1. Volley Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。 名字由来&#xff1a;a burst or emission of many things or a large amount at once 发布演讲…

双击打开Inventor文件

为什么80%的码农都做不了架构师&#xff1f;>>> 出现的问题&#xff1a; 正常启动电脑后&#xff0c;我双击桌面上的一个idw文件&#xff0c;默认使用 Inventor 2013 打开该格式的文件&#xff1b;但 Inventor 启动不到一半就弹出了如下的错误窗口&#xff0c;点击…

phpstrom 编辑器设置

http://www.jb51.net/article/58069.htm 配置sublime主题 保存配置的路径为&#xff1a;将Monokai_Sublime.xml拷贝到C:\Users\Administrator\.WebIde100\config\colors&#xff0c;然后重启phpstrom即可 当主题样式选为暗黑色的时候&#xff0c;选中的代码的背景色也会有点暗…

记一次 .NET 某妇产医院 WPF内存溢出分析

一&#xff1a;背景 1. 讲故事上个月有位朋友通过博客园的短消息找到我&#xff0c;说他的程序存在内存溢出情况&#xff0c;寻求如何解决。要解决还得通过 windbg 分析啦。二&#xff1a;Windbg 分析 1. 为什么会内存溢出大家都知道内存溢出对应着 .NET 中的 OutOfMemonryExce…

16世纪的旷世奇才:大学弃医丛数,仅用20年就独立发明了温度计、军事罗盘、天文望远镜,后半生双目失明还能写出惊人科学著作

全世界只有3.14 % 的人关注了爆炸吧知识传说&#xff0c;在崇尚绝对权威的中世纪里&#xff0c;有这么一位敢于质疑权威的年轻人。在比萨斜塔上做了“两个铁球同时落地”的实验&#xff0c;得出了重量不同的两个铁球同时下落的结论。从此推翻了亚里士多德“物体下落速度和重量成…

禅道项目管理软件介绍

使用流程 一、分享的流程图 二、流程图 维护产品及模块 一、如何来添加产品呢&#xff1f;让我们来看下步骤&#xff1a; 以管理员或者其他有产品管理权限的帐号登录。点击产品视图。在页面右侧&#xff0c;点击“新增产品”&#xff0c;即可出来产品添加页面。&#xff08;第一…

轻松学PHP编程 源代码

http://pan.baidu.com/share/link?shareid170353&uk1191536722 转载于:https://blog.51cto.com/letianwuji/1106854

java jar包 平滑重启,nginx 平滑重启的实现方法

一、背景在服务器开发过程中&#xff0c;难免需要重启服务加载新的代码或配置&#xff0c;如果能够保证server重启的过程中服务不间断&#xff0c;那重启对于业务的影响可以降为0。最近调研了一下nginx平滑重启&#xff0c;觉得很有意思&#xff0c;记录下来供有兴趣的同学查阅…

Android之图形图像之使用Path类总结

Path类可以预先在View上将N个点连成一条"路径",然后调用Canvas的drawPath(path,paint)即可沿着路径绘制图形 Android还为路径绘制提供了PathEffect来定义绘制效果,PathEffect包含如下子类 ComposePathEffect CornerPathEffect DashPathEffect DiscretePathEffect Pat…

[ACM_图论] The Perfect Stall 完美的牛栏(匈牙利算法、最大二分匹配)

描述 农夫约翰上个星期刚刚建好了他的新牛棚&#xff0c;他使用了最新的挤奶技术。不幸的是&#xff0c;由于工程问题&#xff0c;每个牛栏都不一样。第一个星期&#xff0c;农夫约翰随便地让奶牛们进入牛栏&#xff0c;但是问题很快地显露出来&#xff1a;每头奶牛都只愿意在她…

神奇的交际圈!这位17世纪的法国神父结交的好朋友,竟然都是一流数学牛人:笛卡尔、费马、加森迪······

全世界只有3.14 % 的人关注了爆炸吧知识话说&#xff0c;在近代数学史上&#xff0c;人们惊讶地发现17至18世纪的法国竟然产生了众多一流的数学家。然而&#xff0c;最早想到要培养一波优秀人才的&#xff0c;成就这段群星璀璨的传奇历史&#xff0c;并非是君王。而是出自于一位…

[原创]FineUI秘密花园(二十七) — 窗体控件概述(上)

窗体控件在项目中使用非常频繁&#xff0c;同时窗体控件和启用IFrame的面板控件也一起构成了FineUI所特有的内联框架&#xff0c;从而使弹出窗体不再局限于IFrame页面中。本章我们会详细介绍窗体控件的基本用法。 创建窗体控件 在页面中声明窗体控件标签&#xff0c;并设置需要…

Android之AIDL使用详解

1.什么是aidl:aidl是 Android Interface definition language的缩写&#xff0c;一看就明白&#xff0c;它是一种android内部进程通信接口的描述语言&#xff0c;通过它我们可以定义进程间的通信接口 icp:interprocess communication :内部进程通信 2.既然aidl可以定义并实现进…

用php打印九九乘法表,php如何打印出九九乘法表呢?

摘要:下文讲述使用php代码在页面上输出九九乘法表的示例分享&#xff0c;如下所示&#xff1b;实现思路:主要使用遍历的方式输出九九乘法表例:php 循环输出九九乘法表echo "maomao365.com 示例分享\n";echo "for 循环打印出九九乘法表";for($j1; $j<9; …

他言行不一屡次跳槽,还升职加薪走上了人生巅峰,全数学界都炸了......

全世界只有3.14 % 的人关注了爆炸吧知识看在大家都这么爱学习的份上&#xff0c;今天小天就和大家介绍一名老师吧&#xff01;这位老师就是亚历山大.雅科夫列奇.辛钦&#xff01;家庭教育好&#xff0c;学霸就有了亚历山大.雅科夫列奇.辛钦&#xff0c;1894年出生于前苏联莫斯科…

IoTSharp部署教程-Sqlite分表篇

IoTSharp的部署环境极其灵活&#xff0c;我们推荐使用Docker方式进行部署&#xff0c; 这减少了很多配置&#xff0c; 首先最简单的部署当然属于 Sqlite 数据库&#xff0c; 且不适用任何外部依赖。 在生产环境中&#xff0c; 我们需要配置 appsettings.Production.json 文件&a…

Android之AsyncTask两种线程池分析和总结

Android AsyncTask两种线程池分析和总结(一) 前言在android AsyncTask里面有两种线程池供我们调用1&#xff0e; THREAD_POOL_EXECUTOR, 异步线程池2&#xff0e; SERIAL_EXECUTOR&#xff0c;同步线程池正如上面名称描述的那样&#xff0c;一个是异步线程池&#xff…

一款好的折线图、饼图、柱形图

链接地址http://www.highcharts.com/demo/line-basic/skies http://www.highcharts.com/demo/转载于:https://www.cnblogs.com/blueking/p/3530787.html

被遗忘的数学家!曾提出最接地气的数学定理,可以计算男朋友真不真心的那种......

全世界只有3.14 % 的人关注了爆炸吧知识在介绍了业余数学家费马后&#xff0c;听说很多小伙伴还想看看业余的。这不&#xff0c;小天这次又来介绍业余数学家来了。险些被遗忘托马斯.贝叶斯&#xff0c;十八世纪英国的一个长老会的牧师&#xff08;专业&#xff09;和数学家&…

Android之MVVM框架 - 数据绑定

本教程是跟着 Data Binding Guide 学习过程中得出的一些实践经验&#xff0c;同时修改了官方教程的一些错误&#xff0c;每一个知识点都有对应的源码&#xff0c;争取做到实践与理论相结合。 Data Binding 解决了 Android UI 编程中的一个痛点&#xff0c;官方原生支持 MVVM 模…