👉文章示例代码👈

定义

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

四个角色

迭代器模式主要有以下四个角色:

  • 抽象聚合角色Aggregate:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
  • 具体聚合角色Concrete Aggregate:实现抽象聚合类,返回一个具体的迭代器实例。
  • 抽象迭代器Iterator:定义访问和遍历聚合元素的接口。
  • 具体迭代器Concrete Iterator:实现抽象迭代器接口中锁定义的方法,完成对聚合对象的遍历,并且记录遍历的当前位置。

场景示例

笔者这里以超市的商品为例,需要做一个商品清单的展示。

创建商品实体类

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
/**
* @author zhh
* @description 商品实体类
* @date 2020-02-28 14:20
*/
public class Goods {

/**
* 名称
*/
private String name;

/**
* 价格
*/
private double price;

public Goods(String name, double price) {
this.name = name;
this.price = price;
}

public String getName() {
return name;
}

public double getPrice() {
return price;
}
}

创建抽象聚合角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @author zhh
* @description 商品抽象聚合接口
* @date 2020-02-28 14:26
*/
public interface GoodsAggregate {

/**
* 添加商品
*/
void addGoods(Goods goods);

/**
* 删除商品
*/
void removeGoods(Goods goods);

/**
* 获取商品迭代器
*/
GoodsIterator getGoodsIterator();
}

创建具体聚合角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author zhh
* @description 商品具体聚合类
* @date 2020-02-28 14:30
*/
public class GoodsAggregateImpl implements GoodsAggregate {

private List<Goods> goodsList = new ArrayList<Goods>();

public void addGoods(Goods goods) {
goodsList.add(goods);
}

public void removeGoods(Goods goods) {
goodsList.remove(goods);
}

public GoodsIterator getGoodsIterator() {
return new GoodsIteratorImpl(goodsList);
}
}

创建抽象迭代器角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author zhh
* @description 商品抽象迭代器接口
* @date 2020-02-28 14:28
*/
public interface GoodsIterator {

/**
* 获取下一个商品
*/
Goods nextGoods();

/**
* 判断是否还有商品
*/
boolean hasGoods();
}

创建具体迭代器角色

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
/**
* @author zhh
* @description 商品抽象迭代器类
* @date 2020-02-28 14:32
*/
public class GoodsIteratorImpl implements GoodsIterator {

private List<Goods> goodsList;

/**
* 商品位置
*/
private int index;

public GoodsIteratorImpl(List<Goods> goodsList) {
this.goodsList = goodsList;
}

public Goods nextGoods() {
System.out.println("当前商品的位置是" + index);
Goods goods = goodsList.get(index);
index++;
return goods;
}

public boolean hasGoods() {
if (index < goodsList.size()) {
return true;
}
return false;
}
}

测试类及输出

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
/**
* @author zhh
* @description 测试类
* @date 2020-02-28 14:40
*/
public class Test {

public static void main(String[] args) {
// 创建商品
Goods goods1 = new Goods("可乐", 3.0);
Goods goods2 = new Goods("薯片", 5.0);
Goods goods3 = new Goods("奶茶", 3.0);
Goods goods4 = new Goods("香肠", 10.0);
Goods goods5 = new Goods("奶粉", 33.0);
Goods goods6 = new Goods("牛肉干", 23.0);

GoodsAggregate goodsAggregate = new GoodsAggregateImpl();
goodsAggregate.addGoods(goods1);
goodsAggregate.addGoods(goods2);
goodsAggregate.addGoods(goods3);
goodsAggregate.addGoods(goods4);
goodsAggregate.addGoods(goods5);
goodsAggregate.addGoods(goods6);

System.out.println("---商品清单---");
GoodsIterator goodsIterator = goodsAggregate.getGoodsIterator();
Goods goods;
while (goodsIterator.hasGoods()) {
goods = goodsIterator.nextGoods();
System.out.println(String.format("商品名称: %s, 商品价格: %s", goods.getName(), goods.getPrice()));
}
}
}

测试类的输出结果如下:

—商品清单—
当前商品的位置是0
商品名称: 可乐, 商品价格: 3.0
当前商品的位置是1
商品名称: 薯片, 商品价格: 5.0
当前商品的位置是2
商品名称: 奶茶, 商品价格: 3.0
当前商品的位置是3
商品名称: 香肠, 商品价格: 10.0
当前商品的位置是4
商品名称: 奶粉, 商品价格: 33.0
当前商品的位置是5
商品名称: 牛肉干, 商品价格: 23.0

类结构图

以上示例类的结构图如下所示
image.png

总结

适用场景

  • 当访问一个聚合对象中的内容但又不想暴露其内部表示。
  • 需要为聚合对象提供多种的遍历方式。
  • 当需要为遍历不同的聚合结构提供一个统一的接口。

优点

  • 具有良好的封装性,为遍历不同的聚合结构提供了一个统一的接口。
  • 分离了聚合类的遍历行为,简化聚合类。
  • 具有良好的扩展性,新增聚合类和迭代器类无需修改原有代码。

缺点

增加了类的个数,这在一定程度上增加了系统的复杂性。

参考