迭代器模式
一、定义
提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
点击查看源码
二、角色分类
抽象迭代器(Iterator)
定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法
具体迭代器(Concrete Iterator)
实现了抽象迭代器,完成遍历数据元素的具体实现方法,同时在迭代器中通过游标来记录在聚合对象中当前的所处位置,游标通常是一个非负整数
抽象聚合类(Aggregate)
用于存储和管理元素对象,声明了创建迭代器对象的方法,充当抽象迭代器工厂使用
具体聚合类(Concrete Aggregate)
实现了抽象聚合类中声明的创建迭代器对象的方法,该方法返回一个于该具体聚合类对应的具体迭代器实例
客户角色(Client)
具体调用方法的角色
三、实现方式
UML图
![未命名文件 (2).png](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
具体实现
假如我们有一个场景为:医院看病时需要挂号,按照挂号号码来看病,就可以使用迭代器模式实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
@Data @ToString public class Patient {
private String name;
private Integer number;
public Patient(String name, Integer number) { this.name = name; this.number = number; }
public void diagnosis() { System.out.println("医生你好,我是第" + this.number + "号病人" + this.name) } }
|
抽象聚合类(Aggregate)
1 2 3 4 5 6 7 8
| public interface Aggregate { void addPatient(Patient patient);
void removePatient(Patient patient);
PatientIterator createPatientIterator(); }
|
具体聚合类(Concrete Aggregate)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class ConcreteAggregate implements Aggregate { private List<Patient> list;
public ConcreteAggregate() { this.list = new ArrayList<>(); }
@Override public void addPatient(Patient patient) { this.list.add(patient); }
@Override public void removePatient(Patient patient) { this,list.remove(patient); }
@Override public PatientIterator createPatientIterator() { return new PatientIterator(this.list); } }
|
抽象迭代器(Iterator)
1 2 3 4 5
| public interface Iterator { boolean hasNext();
Patient next(); }
|
具体迭代器(Concrete Iterator)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class PatientIterator implements Iterator { private List<Patient> list; private int position = 0; private Patient currentPatient;
public PatientIterator(List<Patient> list) { this.list = list; }
@Override public boolean hasNext() { return position < list.size; }
@Override public Patient next(){ currentPatient = list.get(position); position++; return currentPatient; } }
|
客户角色(Client)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Client { public static void main(String[] args) { Aggregate doctorA = new ConcreteAggregate(); doctorA.addPatient(new Patient("张三", 1)); doctorA.addPatient(new Patient("李四", 2)); doctorA.addPatient(new Patient("王五", 3)); doctorA.addPatient(new Patient("赵六", 4));
Iterator iterator = doctorA.createPatientIterator(); while (iterator.hasNext()) { Patient patient = iterator.next(); patient.diagnosis(); } } }
|
运行结果
1 2 3 4
| 医生你好,我是第1号病人张三 医生你好,我是第2号病人李四 医生你好,我是第3号病人王五 医生你好,我是第4号病人赵六
|
四、应用场景
以下部分内容摘自菜鸟教程
意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决: 不同的方式来遍历整个整合对象。
何时使用: 遍历一个聚合对象。
如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码: 定义接口:hasNext, next。
应用实例: JAVA 中的 iterator。
使用场景:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 需要为聚合对象提供多种遍历方式。
- 为遍历不同的聚合结构提供一个统一的接口。
注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
五、优缺点
优点
- 它支持以不同的方式遍历一个聚合对象。
- 迭代器简化了聚合类。
- 在同一个聚合上可以有多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。