16.java设计模式之迭代器模式
基本需求:
- 展示一个学校的结构,比如一个学校下面有多个学院,学院下面有多个系,对其节点主要是遍历,与组合模式略有不同
传统方案:
- 学校<-学院<-系 依次继承
- 这种方式,在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系,因此这种方案,不能很好实现的遍历的操作,并且他们之间也没有继承关系,使用继承并不合适
基本介绍:
迭代器模式(Iterator)是常用的设计模式,属于行为型模式,这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示
如果我们的集合元素是用不同的方式实现的,有数组,还有java的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决
迭代器模式提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构
把在元素之间游走的责任交给迭代器,而不是聚合对象
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性
UML类图(原理)
- 说明
- Iterator:迭代器接口,直接使用JDK提供的即可提供,含有hasNext, next, remove
- ConcreteIterator:具体的迭代器类,进行元素迭代,其内部元素的以不同的方式进行存储,例如数组、list等
- Aggregate:一个统一的聚合接口,将客户端和具体聚合解耦,进行元素的存储
- ConcreteAggreage:具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历集合,和ConcreteIterator一一对应
- Element:集合内部所存储的元素
- 实际情况中一般将ConcreteIterator作为内部类放入ConcreteAggreage类中,直接省去了元素集合elementes的传递
UML类图(案例)
- 说明
- OutputImpl:用于输出信息的辅助类
代码实现
迭代器类不作为持有迭代集合类的内部类
@Data
@AllArgsConstructor
public class Department { // 迭代器内部元素 private String name; private String description; }
public class ComputerCollegeIterator implements Iterator { // 计算机学院迭代器,元素使用数组存储 一般会将迭代器实现类作为需要迭代对象的内部类 private Department[] departments; // 当前位置指针
private int index = 0; public ComputerCollegeIterator(Department[] departments) {
this.departments = departments;
} // 判断是否有下一个元素
@Override
public boolean hasNext() {
return !(this.index >= this.departments.length);
} // 返回下一个元素
@Override
public Department next() {
return this.departments[this.index++];
} @Override
public void remove() {
// 移除方法空实现
} }
public class InfoCollegeIterator implements Iterator { // 信息工程学院迭代器,元素使用List集合存储 一般会将迭代器实现类作为需要迭代对象的内部类 private List<Department> departments; // 当前位置指针
private int index = 0; public InfoCollegeIterator(List<Department> departments) {
this.departments = departments;
} // 判断是否有下一个元素
@Override
public boolean hasNext() {
return !(this.index >= this.departments.size());
} // 返回下一个元素
@Override
public Department next() {
return this.departments.get(this.index++);
} @Override
public void remove() {
// 移除方法空实现
} }
public interface College { // 学院接口 // 获取学院名称
String getName(); // 给学院内部添加系
void addDepartment(String name, String description); // 获取该学院所对应的迭代器
Iterator createIterator(); } // 实现类一 计算机学院
class ComputerCollege implements College { // 存储内部元素的集合,用于获取迭代器
private Department[] departments; // 当前元素位置指针
private int index; public ComputerCollege() {
this.departments = new Department[5];
this.index = 0;
addDepartment("Java专业", "Java专业 ");
addDepartment("PHP专业", "PHP专业 ");
addDepartment("大数据专业", "大数据专业");
} @Override
public String getName() {
return "计算机学院";
} @Override
public void addDepartment(String name, String description) {
Department department = new Department(name, description);
this.departments[this.index++] = department;
} @Override
public Iterator createIterator() {
return new ComputerCollegeIterator(this.departments);
} } // 实现类二 信息工程学院
class InfoCollege implements College { // 存储内部元素的集合,用于获取迭代器
private List<Department> departments; public InfoCollege() {
this.departments = new ArrayList<Department>();
addDepartment("信息安全专业", "信息安全专业");
addDepartment("网络安全专业", "网络安全专业");
addDepartment("服务器安全专业", "服务器安全专业");
} @Override
public String getName() {
return "信息工程学院";
} @Override
public void addDepartment(String name, String description) {
this.departments.add(new Department(name, description));
} @Override
public Iterator createIterator() {
return new InfoCollegeIterator(this.departments);
} }
public class OutputImpl { // 输出迭代器元素内部的实现类 private List<College> colleges; public OutputImpl(List<College> colleges) {
this.colleges = colleges;
} public void printCollege() {
// 获取List集合内部的迭代器
Iterator<College> iterator = colleges.iterator();
while (iterator.hasNext()) {
College college = iterator.next();
System.out.println("======" + college.getName() + "======");
// 获取学院内部系的迭代器进行迭代输出 而不需要知道元素再内部以什么形式的集合存在,统一了遍历方式
printDepartment(college.createIterator());
}
} private void printDepartment(Iterator iterator) {
while (iterator.hasNext()) {
Department department = (Department) iterator.next();
if (null != department) {
System.out.println(department.getName() + "-----" + department.getDescription());
}
}
} }public class Client {
public static void main(String[] args) {
// 创建学院的集合
List<College> colleges = new ArrayList<College>();
colleges.add(new ComputerCollege());
colleges.add(new InfoCollege());
// 创建输出类 并迭代输出学院及其下面的系
OutputImpl output = new OutputImpl(colleges);
output.printCollege();
}
}
迭代器类作为持有迭代集合类的内部类
// 实现类一 计算机学院
public class ComputerCollege implements College { // 存储内部元素的集合,用于获取迭代器
private Department[] departments; // 当前元素位置指针
private int index; public ComputerCollege() {
this.departments = new Department[5];
this.index = 0;
addDepartment("Java专业", "Java专业 ");
addDepartment("PHP专业", "PHP专业 ");
addDepartment("大数据专业", "大数据专业");
} @Override
public String getName() {
return "计算机学院";
} @Override
public void addDepartment(String name, String description) {
Department department = new Department(name, description);
this.departments[this.index++] = department;
} @Override
public Iterator createIterator() {
return new ComputerCollegeIterator();
} // 迭代器类作为持有迭代集合类的内部类
private class ComputerCollegeIterator implements Iterator { // 计算机学院迭代器,元素使用数组存储 一般会将迭代器实现类作为需要迭代对象的内部类 // 当前位置指针
private int index = 0; // 判断是否有下一个元素 直接使用上层类的元素集合即可
@Override
public boolean hasNext() {
return !(this.index >= ComputerCollege.this.departments.length);
} // 返回下一个元素 直接使用上层类的元素集合即可
@Override
public Department next() {
return ComputerCollege.this.departments[this.index++];
} @Override
public void remove() {
// 移除方法空实现
} } }
// 实现类二 信息工程学院
public class InfoCollege implements College { // 存储内部元素的集合,用于获取迭代器
private List<Department> departments; public InfoCollege() {
this.departments = new ArrayList<Department>();
addDepartment("信息安全专业", "信息安全专业");
addDepartment("网络安全专业", "网络安全专业");
addDepartment("服务器安全专业", "服务器安全专业");
} @Override
public String getName() {
return "信息工程学院";
} @Override
public void addDepartment(String name, String description) {
this.departments.add(new Department(name, description));
} @Override
public Iterator createIterator() {
return new InfoCollegeIterator();
} // 迭代器类作为持有迭代集合类的内部类
private class InfoCollegeIterator implements Iterator { // 信息工程学院迭代器,元素使用List集合存储 一般会将迭代器实现类作为需要迭代对象的内部类 // 当前位置指针
private int index = 0; // 判断是否有下一个元素 直接使用上层类的元素集合即可
@Override
public boolean hasNext() {
return !(this.index >= InfoCollege.this.departments.size());
} // 返回下一个元素 直接使用上层类的元素集合即可
@Override
public Department next() {
return InfoCollege.this.departments.get(this.index++);
} @Override
public void remove() {
// 移除方法空实现
} } }
jdk源码:
在jdk的ArrayList源码中就使用到了迭代器模式
UML类图
说明
List就是充当了聚合接口,含有一个iterator()方法,返回一个迭代器对象
ArrayList是实现聚合接口List的子类,实现了iterator()
ArrayList内部的elementData属性就是存放元素的集合,是一个数组Object[]
Itr充当具体实现迭代器Iterator的类,作为ArrayList内部类
Iterator接口JDk提供
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
// 存储元素的集合
transient Object[] elementData; // 实现获取迭代器方法
public Iterator<E> iterator() {
return new Itr();
} /**
* An optimized version of AbstractList.Itr
*/
// 作为ArrayList内部类 实现迭代器Iterator
private class Itr implements Iterator<E> {
......
}
}
注意事项:
- 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了
- 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成
- 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器
- 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式
- 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
16.java设计模式之迭代器模式的更多相关文章
- 折腾Java设计模式之迭代器模式
迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...
- 简单的了解下Java设计模式:迭代器模式(转载)
迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. Java 开发过程中遍历是常用的.如下边程序: for(int i =0 ; ...
- java设计模式之迭代器模式
一.迭代器模式简介 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露内部的表示.把游走的任务放在迭代器上,而不是 ...
- Python进阶:设计模式之迭代器模式
在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- Java设计模式之builder模式
Java设计模式之builder模式 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成的.再次整理一下什么是builder模式以及应用场景. 1. ...
- 实践GoF的设计模式:迭代器模式
摘要:迭代器模式主要用在访问对象集合的场景,能够向客户端隐藏集合的实现细节. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:迭代器模式>,作者:元闰子. 简介 有时会遇到这 ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
随机推荐
- 如何做可靠的分布式锁,Redlock真的可行么
本文是对 Martin Kleppmann 的文章 How to do distributed locking 部分内容的翻译和总结,上次写 Redlock 的原因就是看到了 Martin 的这篇文章 ...
- Java_Math类和Random类
Math类 java.lang.Math提供了一系列静态方法用于科学计算, 其方法的参数和返回值类型一般都为double型, 如果需要更加强大的数学运算能力计算高等数学中的相关内容, 可使用apach ...
- 内网渗透 day7-linux信息收集
linux信息搜集 目录 1. linux信息搜集 2. nmap漏洞复现 3. msf linux模块反弹shell 1. linux信息搜集 id 查看当前用户的权限和所在的管理组 python ...
- WEB安全问题
WEB安全问题我没太多经验,但是这块内容还是很重要,所以必须要了解学习一下. 简单总结了一下,分成以下5类, 1.DDOS,瘫痪式攻击,解决方法是记录异常请求的ip地址,主动拒绝或者将攻击ip添加到防 ...
- margin的讲究
什么元素允许有margin值,无论块状元素还是行内元素都可以,只是各有限制. 先说行内元素,这个是不允许有上下 外边距的, 再说块状元素,上下左右外边距都允许 但是相邻元素的外边距会合并,要注意的是 ...
- [MIT6.006] 12. Square Roots, Newton's Method 平方根,牛顿法
首先让我们回顾下上节课讲的,用牛顿法计算√2的内容: 简单来说,牛顿法从x0=1不断向后计算逼近√2的值,而刚开始计算的精度是1,随着牛顿法的逼近(共log2d个循环),就能使得√2逼近值的精度达到d ...
- 牛客网-声网2020校招-通用C++笔试题-2020.9.3
1. 操作系统中两个进程争夺同一个资源会发生什么情况? 答:不一定死锁 解析:产生死锁的四个必要条件为 (1)互斥条件:一个资源每次只能被一个进程使用. (2)不可剥夺条件:进程已获得的资源,在未使用 ...
- Fiddler的一系列学习瞎记3
Http: 不安全.可以很容易被拦截,或者其他的嗅探工具发现.怎么样做到安全?起码一下两点: 1.浏览器和we服务器之间的内容应该只有浏览器和web服务器能看到通信内容. 2.Http请求和Http的 ...
- Docker与Ceph的分与合
前言 docker是一个管理工具,在操作系统之上提供了一个新的独立轻环境,好处是本地提供了一个基础镜像,然后基于镜像再运行环境,也可以把环境重新打包为镜像,管理起来类似于git,感觉非常的方便,并且能 ...
- 利用移动硬盘安装windows7系统
首先把win7系统镜像的iso文件解压到移动硬盘中 将移动硬盘设置为活动分区 设置活动分区的方法 Diskpart程序实现U盘安装WIN7的方法: 将Win7安装盘中的所有文件拷贝到硬盘文件夹中,我们 ...