浅谈设计模式 - 迭代器模式(十一)
前言
迭代器模式通常只须要晓得该模式的实现原理和理解结构图即可,在设计模式当中本人实现的状况简直是没有的,所以这个模式简略的过一遍。
什么是迭代器模式
定义:提供程序的办法拜访一个聚合对象的各个元素,同时又不会裸露外部的性能
迭代器模式通过接管遍历的细节,让提供方不用关怀迭代的具体细节,只须要提供对应的聚合对象即可。
迭代器模式和加强的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语言中根本曾经实现到汇合当中,当咱们遍历汇合的时候,其实就是在应用迭代器,迭代器通过封装遍历解耦了一堆对象的遍历和创立工作,将迭代的细节封装到一个黑盒当中,内部只须要调用接口就能够操作汇合的数据。