迭代器模式

迭代器模式

一、定义

提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

点击查看源码


二、角色分类

抽象迭代器(Iterator)

定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法

具体迭代器(Concrete Iterator)

实现了抽象迭代器,完成遍历数据元素的具体实现方法,同时在迭代器中通过游标来记录在聚合对象中当前的所处位置,游标通常是一个非负整数

抽象聚合类(Aggregate)

用于存储和管理元素对象,声明了创建迭代器对象的方法,充当抽象迭代器工厂使用

具体聚合类(Concrete Aggregate)

实现了抽象聚合类中声明的创建迭代器对象的方法,该方法返回一个于该具体聚合类对应的具体迭代器实例

客户角色(Client)

具体调用方法的角色


三、实现方式

UML图

未命名文件 (2).png

具体实现

假如我们有一个场景为:医院看病时需要挂号,按照挂号号码来看病,就可以使用迭代器模式实现

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。

使用场景:

  1. 访问一个聚合对象的内容而无须暴露它的内部表示。
  2. 需要为聚合对象提供多种遍历方式。
  3. 为遍历不同的聚合结构提供一个统一的接口。

注意事项: 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。


五、优缺点

优点

  1. 它支持以不同的方式遍历一个聚合对象。
  2. 迭代器简化了聚合类。
  3. 在同一个聚合上可以有多个遍历。
  4. 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。