设计模式 ( 十四 ) 迭代器模式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,一经查实,立即删除!

相关文章

开源网站

开源网站&#xff1a; Code Google 谷歌旗下的一个开源项目托管网站&#xff0c;资源很丰富&#xff0c;文档也很齐全&#xff0c;甚至还有中文文档。 Souceforge 国外一个比较有名的开源网站&#xff0c;很多有名的开源项目都是在这个网站托管的。 Github 也很不错的一个开源网…

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;点击…

php long2ip,php 中IPV6 ip2long的问题解决办法

在32位系统&#xff0c;ip2long不能转换IPv6&#xff0c;但您可以转换ip2bin和bin2ip 这个函数转换为IPv4和IPv6&#xff0c;返回false&#xff0c;如果是无效的实例程序 代码如下复制代码function ip2bin($ip){if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ! fa…

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;每头奶牛都只愿意在她…

js调用高德API获取所在当前城市

可以在js代码中直接调用API接口&#xff0c;获取所处当前城市信息&#xff0c;代码如下&#xff1a; <script type"text/javascript">function getCurrentCity(){$.ajax({type: "get",url: "http://webapi.amap.com/maps/ipLocation?key608d75…

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

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

如何在 ASP.NET Core 中为 gRPC 服务添加全局异常处理 ?

咨询区 Dmitriy我在 ASP.NET Core 中使用 GRPC.ASPNETCore 工具包写 gRPC 服务&#xff0c;现在我想实现 gRPC 的异常全局拦截&#xff0c;我的代码如下&#xff1a;app.UseExceptionHandler(configure > {configure.Run(async e >{Console.WriteLine("Exception te…

[原创]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; …

CentOS 安装jdk1.7 64位

[rootlocalhost ~]# java -versionjava version "1.6.0"OpenJDK Runtime Environment (build 1.6.0-b09)OpenJDK 64-Bit Server VM (build 1.6.0-b09, mixed mode) 1.6的&#xff0c;这个必须换掉 。下载jdk-7u3-linux-x64.rpm # wget http://download.oracle.com/o…

LeetCode-Add Binary

Given two binary strings, return their sum (also a binary string).For example, a "11" b "1" Return "100". 这道题不难&#xff0c;注意分清情况。 public class Solution {public String addBinary(String a, String b) {String str&qu…