共计 4210 个字符,预计需要花费 11 分钟才能阅读完成。
浅谈设计模式 – 迭代器模式(十一)
前言
迭代器模式通常只须要晓得该模式的实现原理和理解结构图即可,在设计模式当中本人实现的状况简直是没有的,所以这个模式简略的过一遍。
什么是迭代器模式
定义:提供程序的办法拜访一个聚合对象的各个元素,同时又不会裸露外部的性能
迭代器模式通过接管遍历的细节,让提供方不用关怀迭代的具体细节,只须要提供对应的聚合对象即可。
迭代器模式和加强的 FOR 循环:
Jdk1.5 之后,将泛型和加强 for 循环退出到语言体系,能够间接对于汇合的内容进行 for 循环查看,其实实质上还是调用了 iterator 办法,而 java 通过语法糖的模式为咱们进行的遍历的暗藏。
迭代器模式结构图
迭代器模式的结构图如下:
Aggregate:聚合对象的独特接口,定义了具备遍历性能的聚合对象,通过定义创立迭代器的接口来建设与迭代器的组合
ConcreateAggregate:具体的迭代器实现对象,通过接口办法返回具体的迭代器实现
Iterator:迭代器接口,定义迭代器的对立标准,所以派生类都须要强制依照接口标准执行迭代器的实现。保障迭代器具备类似的行为。ConcreteIterator:具体的迭代器实现,外部聚合对象的同时,能够扩大迭代器的遍历形式,比方 ListIterator。
迭代器模式特点
- 迭代器将遍历的细节进行了封装,聚合对象不须要在关怀客户端如何操作外部的变量,而是通过委托给迭代器的模式交由迭代器去实现具体的遍历细节。
- 迭代器能够在 不裸露内部结构的同时让外界能够拜访到外部的聚合对象,所以即便是齐全不同的对象也能够对立看待和解决。
- 迭代器是一种职责的转移,将遍历的工作从本来的聚合对象中进行独立,能在 不改变数据结构的同时扭转数据的操作形式。
迭代器的注意事项:
- 须要留神迭代器存在 外部的迭代器 和内部的迭代器,外部的迭代器供对象自身应用不对外开放,内部的迭代器通过办法返回给调用方应用。
- 每个责任对应一个区域,超过区域象征多了一个责任,遍历和数据操作实际上是两个操作,应该辨别看待。
- 留神迭代器是如何体现繁多职责的准则,他剥离了遍历对象的性能,将其封装到一个迭代器外部进行应用。
- 好的迭代器该当具备“疾速失败机制”,目标是为了避免操作外部元素的指针越界,同时及时告诉客户端遍历异样。
- 如果想让办法不反对某些性能,最好应用异样机制揭示客户端我不反对某些操作。
案例
光有实践还是不够的,这里配合代码解说迭代器是如何实现解耦聚合对象的遍历的。
模仿场景:
因为迭代器在理论工作中应用概率 简直为 0 ,这里设置的场景比较简单
咱们应用 window 最常见的文件系统来作为案例,咱们通常进入不同的磁盘,首先就是对该磁盘上面的第一级目录进行遍历,同时咱们依据遍历形式的不同,能够将页面展现为分组,依照工夫排序,显示不同的详略信息 ….. 这些性能的实质都是遍历,只不过遍历的模式不同,为了实现对于菜单的不同模式遍历,咱们通过定义不同迭代器来实现这一个指标。
接着,咱们会发现迭代的品种丰盛还不够,咱们还须要迭代其余的内容,比方工作管理器须要迭代不同的过程,同样也蕴含了排序的或者暗藏局部过程等等一系列的性能,所以须要让不同的对象能够撑持类似的迭代操作,并且能够自在的替换迭代的形式,当然这部分性能不会放入案例局部,案例局部为简略的迭代器实现。
具体实现
在进行具体的编码之前,先检查一下须要的根本构建类:
Travelsable:定义对象具备迭代的性能接口。MissionBoard:任务栏,储存根本的工作信息,提供迭代器供内部展现。TaskItemlIterator:工作迭代器,用于工作的迭代操作
ConcreteCatalogIterator:目录迭代器的实现具体子类,定义了不同的迭代品种。TaskItem 工作项,定义一个工作的内容
Computer 电脑,只须要治理任务栏和文件管理器即可。FileManager 文件管理器,负责管理文件夹的内容
FileIterator 文件迭代器,治理文件夹的迭代操作
FileItem 文件项
上面间接依照结构图构建具体代码:
// 电脑,只须要治理任务栏和文件管理器即可。public class Computer {
private FileManager fileManager;
private MissionBoard missionBoard;
public Computer(FileManager fileManager, MissionBoard missionBoard) {
this.fileManager = fileManager;
this.missionBoard = missionBoard;
}
public void display(){Iterator fileManagerIterator = fileManager.createIterator();
Iterator missionBoardIterator = missionBoard.createIterator();
while (fileManagerIterator.hasNext()){Object next = fileManagerIterator.next();
System.out.println(next);
}
while (missionBoardIterator.hasNext()){Object next = missionBoardIterator.next();
System.out.println(next);
}
}
}
// 文件项
public class FileItem {
private String fileName;
private String editDate;
private String ceateDate;
private long size;
// 省略局部内容
}
// 工作项
public class TaskItem {
private String name;
private int size;
// 省略局部内容
}
// 迭代器标准接口
public interface Travelsable<E extends Object>{
/**
* 创立迭代器的办法
* @return
*/
Iterator<E> createIterator();}
// 任务栏,治理工作项. 实现接口,反对迭代操作
public class MissionBoard implements Travelsable {
private Stack<TaskItem> taskItems;
public MissionBoard() {taskItems = new Stack<>();
taskItems.push(new TaskItem("工作 1", 10));
taskItems.push(new TaskItem("工作 2", 1230));
taskItems.push(new TaskItem("工作 3", 123));
taskItems.push(new TaskItem("工作 4", 414));
taskItems.push(new TaskItem("工作 5", 555));
}
@Override
public Iterator createIterator() {return new TaskItemlIterator(taskItems);
}
}
// 文件管理器,管理文件项,实现接口并且反对迭代操作
public class FileManager implements Travelsable{private FileItem[] fileItems;
public FileManager() {this.fileItems = new FileItem[10];
Random random = new Random(10000);
for (int i = 0; i < fileItems.length; i++) {fileItems[i] = new FileItem("文件"+i, random.nextInt(2000));
}
}
@Override
public Iterator createIterator() {return new FileIterator(fileItems);
}
}
// 文件迭代器
public class FileIterator implements Iterator{private FileItem[] fileItems;
private int index;
public FileIterator(FileItem[] fileItems) {
this.fileItems = fileItems;
this.index = 0;
}
@Override
public boolean hasNext() {return index++ < fileItems.length - 1;}
@Override
public Object next() {return fileItems[index];
}
@Override
public void remove(Object ele) {throw new UnsupportedOperationException("数组不反对以后操作");
}
}
// 工作迭代器
public class TaskItemlIterator implements Iterator{
private Stack<TaskItem> taskItems;
public TaskItemlIterator(Stack<TaskItem> taskItems) {this.taskItems = taskItems;}
@Override
public boolean hasNext() {if(taskItems.isEmpty()){return false;}
TaskItem peek = taskItems.peek();
return peek != null;
}
@Override
public Object next() {return taskItems.pop();
}
@Override
public void remove(Object ele) {taskItems.remove(ele);
}
}
以上就是迭代的大抵实现案例代码,古代编程根本不会本人去设计迭代器,所以理解概念和晓得样板代码即可。
总结:
迭代器在 JAVA 语言中根本曾经实现到汇合当中,当咱们遍历汇合的时候,其实就是在应用迭代器,迭代器通过 封装遍历 解耦了一堆对象的遍历和创立工作,将迭代的细节封装到一个黑盒当中,内部只须要调用接口就能够操作汇合的数据。