设计模式-迭代器模式

迭代器模式(Iterator Pattern): 提供一种方法顺序访问一个聚合对象中的各个元素, 而又不用暴露该对象的内部表示.

设计模式-概述

集合对象一般都有两种职责, 一个是存储数据;二是遍历数据. 迭代器模式就是把第二种职责分离开来, 由迭代器来负责聚合对象内部元素的遍历行为. 它是一种对象行为模式.

结构

它包含了4种角色:

  1. 抽象迭代器(Iterator): 它定义了访问和遍历元素的接口, 声明了用与遍历元素的方法.
  2. 具体迭代器(ConcreteIterator): 实现了抽象迭代器, 完成对于聚合对象的遍历.
  3. 抽象聚合类(Aggregate): 存储和管理元素对象, 声明一个 createIterator()方法用于创建一个迭代器对象.
  4. 具体聚合类(ConcreteAggregate): 抽象聚合类的子类, 实现了createIterator()方法, 返回一个迭代器实例.

iterator-1.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
27
28
29
30
31
@@startuml iterator-1
!include common.cuml

Interface(Iterator,"抽象迭代器") {
+ first()
+ next()
+ hasNext()
+ currentItem()
}

Class(ConcreteIterator,"具体迭代器") {
+ first()
+ next()
+ hasNext()
+ currentItem()
}

Class(Aggregate,"抽象聚合类") <<abstract>> {
+ createIterator() : Iterator
}

Class(ConcreteAggregate,"具体聚合类") {
+ createIterator() : Iterator
}

Aggregate <|.. ConcreteAggregate
ConcreteAggregate .left.> ConcreteIterator
ConcreteAggregate <-right- ConcreteIterator : aggregate
Iterator <|.. ConcreteIterator

@@enduml

代码实现

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.yuda.desigmode.main5;

/**
* @author canyu
* @create_date 2020/12/4 12:39
*/
public class Main {
public static void main(String[] args) {
ConcreteAggregate concreteAggregate = new ConcreteAggregate();
Iterator iterator = concreteAggregate.createIterator();
iterator.first();
iterator.hasNext();
iterator.next();
iterator.currentItem();
}
}

interface Iterator {
void first();

void next();

boolean hasNext();

Object currentItem();
}

class ConcreteIterator implements Iterator {

private ConcreteAggregate objects;

private int cursor;

public ConcreteIterator(ConcreteAggregate objects) {
this.objects = objects;
}

@Override
public void first() {
System.out.println("ConcreteIterator.first");
}

@Override
public void next() {
System.out.println("ConcreteIterator.next");
}

@Override
public boolean hasNext() {
System.out.println("ConcreteIterator.hasNext");
return false;
}

@Override
public Object currentItem() {
System.out.println("ConcreteIterator.currentItem");
return objects;
}
}

abstract class Aggregate {
abstract Iterator createIterator();
}

class ConcreteAggregate extends Aggregate {

@Override
Iterator createIterator() {
return new ConcreteIterator(this);
}
}

使用场景

  1. 同一个聚合对象如果有多种变量方式, 可以使用迭代器模式, 具体的遍历方式封装到迭代器中, 使用不同迭代器来实现不同的遍历方式, 需要多种遍历方式时使用.
  2. 聚合对象不需要再考虑维护遍历方式, 仅仅专注于保存数据, 遍历聚合对象无需关注内部实现时使用.
  3. 遍历元素的客户端使用统一的接口时, 使用迭代器模式能简化遍历方式.

具体应用

  1. JDK中的集合接口Collection, 继承了Iterable接口, 实现了Collection的集合类都有实现遍历方法.
  2. MyBatis中当查询数据库返回大量的数据项时可以使用游标 Cursor, 利用其中的迭代器可以懒加载数据, 避免因为一次性加载所有数据导致内存奔溃, Mybatis 为 Cursor 接口提供了一个默认实现类 DefaultCursor.