看一个具体的需求
编写程序展示一个学校院系结构:需求是这样
要在一个页面中展示出学校的院系组成,
一个学校有多个学院,
一个学院有多个系。
如图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/1e502671db4b4941908d740f07b9d104.png)
传统的设计方案(类图)
![在这里插入图片描述](https://img-blog.csdnimg.cn/28d6202179b04dfe839683a69ab03b6a.png)
传统的方式的问题分析
-
将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
-
实际上我们的要求是 :在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因此这种方案,不能很好实现的遍历的操作
-
解决方案:=> 迭代器模式
迭代器模式基本介绍
- 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式
- 如果我们的集合元素是用不同的方式实现的,有数组,还有 java 的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
- 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。
迭代器模式的原理类图
![在这里插入图片描述](https://img-blog.csdnimg.cn/692e670327434da6ba1c02bbd5f7f9e9.png)
对原理类图的说明-即(迭代器模式的角色及职责)
- Iterator : 迭代器接口,是系统提供,含义 hasNext, next, remove
- ConcreteIterator : 具体的迭代器类,管理迭代
- Aggregate :一个统一的聚合接口, 将客户端和具体聚合解耦
- ConcreteAggreage : 具体的聚合持有对象集合, 并提供一个方法,返回一个迭代器, 该迭代器可以正确遍历集合
- Client :客户端, 通过 Iterator 和 Aggregate 依赖子类
迭代器模式应用实例
编写程序展示一个学校院系结构:需求是这样,
要在一个页面中展示出学校的院系组成,
一个学校有多个学院,
一个学院有多个系。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d454bee81c35455d8a83aaae4fb9ba16.png)
College类,学院超类
![在这里插入图片描述](https://img-blog.csdnimg.cn/9cc3495328be4843a3b23361308f72d5.png)
ComputerCollege类,计算机学院
![在这里插入图片描述](https://img-blog.csdnimg.cn/7e5d3e5718ef465f987cddea99289f48.png)
里面的专业(Department)是以数组方式存储的
Department类
![在这里插入图片描述](https://img-blog.csdnimg.cn/af0160e350a249ce98a57316f18afcd6.png)
InfoCollege类,信息工程学院
![在这里插入图片描述](https://img-blog.csdnimg.cn/669605a2e07f4f84b3eefe46db1a2133.png)
这里面的专业(Department)是以列表方式存储的
ComputerCollegeIterator类,计算机学院具体迭代类,需要实现Iterator接口
![在这里插入图片描述](https://img-blog.csdnimg.cn/96ffb6c364264639bc84aa34f8be1614.png)
InfoColleageIterator类,信息工程学院具体迭代类,需要实现Iterator接口
![在这里插入图片描述](https://img-blog.csdnimg.cn/f961df5027f143e19b43958495251652.png)
OutPutImpl类,统一打印信息
![在这里插入图片描述](https://img-blog.csdnimg.cn/7e5d45579cb646749707066613be7573.png)
Client类,客户端类
![在这里插入图片描述](https://img-blog.csdnimg.cn/a210fdb788504e06bf189f50dd26154a.png)
运行结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/6bef8a9383cb40448ab0ca2684823e51.png)
老规矩,debug看看
![在这里插入图片描述](https://img-blog.csdnimg.cn/3e24f164867b4fca9fcb337f1cbf8eac.png)
这里构建了一个含有计算机学院和信息工程学院的list传入到OutPutImpl的构造函数中去
![在这里插入图片描述](https://img-blog.csdnimg.cn/192f67d935bf40a9ab7808ae62e3b543.png)
可以看到outPutImpl被实例之后的对象含有一个列表成员变量
进入printCollege方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/95cd5ffb7b94460a8b0de46313921fb7.png)
这里调用的是list里面的Iterator拿出每个学院出来,并且打印名称
![在这里插入图片描述](https://img-blog.csdnimg.cn/49d1e9042bde4d2ca0e0dc01ee822f27.png)
college.createIterator()方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/e182a7e84482407391f33800ada9b47e.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ec0cd3efc2eb40a4bdc17c6c5344a213.png)
这里返回了一个具体的迭代器
![在这里插入图片描述](https://img-blog.csdnimg.cn/87b4650b5d44428ab475e619a92752dd.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/b09490642f684edb9ac54c5823d78cbc.png)
再回到printDepartment方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/6f849b05da2f492b94be932fb83f40ef.png)
这里的迭代器是一个计算机学院迭代器
![在这里插入图片描述](https://img-blog.csdnimg.cn/9199c03c784e49488ccac6810f0007e4.png)
所以他就会走我们自己的实现
![在这里插入图片描述](https://img-blog.csdnimg.cn/9ebcc93711ac4e0ca6bf5e8e79b57828.png)
接着拿到专业
![在这里插入图片描述](https://img-blog.csdnimg.cn/b633d73700644e3f951cf334c5318471.png)
输出专业名称
![在这里插入图片描述](https://img-blog.csdnimg.cn/2d80e6583eac4c339a86b9e4a3846c17.png)
信息工程学院亦是如此
这样OutPutImpl这个类其实并不知道具体的迭代器是什么,就将我们的内部细节给隐藏起来了
迭代器模式在JDK中的源码分析
JDK 的 ArrayList 集合中就使用了迭代器模式
代码分析
ArrayList类
![在这里插入图片描述](https://img-blog.csdnimg.cn/2e12e8ac961c4ceda4570dccc7461993.png)
ArrayList的iterator方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/33965dbf96ad44b4bb9eab9967295ded.png)
返回了一个Itr类
他是ArrayList里面的实现了iterator的内部类
![在这里插入图片描述](https://img-blog.csdnimg.cn/1c9ac232f094429980c3a601ec7bf58c.png)
他存在的成员变量elementData存储数据
![在这里插入图片描述](https://img-blog.csdnimg.cn/598e753bd8cc4be698639758d9e6de68.png)
然后我们看看linkedlist
![在这里插入图片描述](https://img-blog.csdnimg.cn/443d352a2afc41d3b75e2f4fae6c5430.png)
他的父类AbstractSequentialList有一个iterator方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/934d0d4be5d34d8da4d3e66311150527.png)
实际调用的是AbstractSequentialList的父类AbstractList里面的listIterator方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/e35ad03a89b9402c8d2acc2aff74def8.png)
实际返回的是AbstractList内部类ListItr
![在这里插入图片描述](https://img-blog.csdnimg.cn/3add5809d31d42ec8d0951c26b52d388.png)
对类图的角色分析和说明
![在这里插入图片描述](https://img-blog.csdnimg.cn/af49b5b5e06a4a4bb76d6691d0ae0e5a.png)
- 内部类 Itr 充当具体实现迭代器 Iterator 的类, 作为 ArrayList 内部类,类似ConcreteIterator
- List 就是充当了聚合接口,含有一个 iterator() 方法,返回一个迭代器对象,类似Aggregate
- ArrayList 是实现聚合接口 List 的子类,实现了 iterator(),类似ConcreteAggreage
- Iterator 接口系统提供
迭代器模式解决了 不同集合(ArrayList ,LinkedList) 统一遍历问题
迭代器模式的注意事项和细节
优点
- 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
- 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
- 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。
- 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
缺点
- 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
资料参考:https://www.bilibili.com/video/BV1G4411c7N4
代码地址:https://gitee.com/WangFuGui-Ma/design-pattern/tree/master/design
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)