附链
你也可以在这些平台阅读本文:
定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
四个角色
迭代器模式主要有以下四个角色:
- 抽象聚合角色Aggregate:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
- 具体聚合角色Concrete Aggregate:实现抽象聚合类,返回一个具体的迭代器实例。
- 抽象迭代器Iterator:定义访问和遍历聚合元素的接口。
- 具体迭代器Concrete Iterator:实现抽象迭代器接口中锁定义的方法,完成对聚合对象的遍历,并且记录遍历的当前位置。
场景示例
笔者这里以超市的商品为例,需要做一个商品清单的展示。
创建商品实体类
/**
* @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;
}
}
创建抽象聚合角色
/**
* @author zhh
* @description 商品抽象聚合接口
* @date 2020-02-28 14:26
*/
public interface GoodsAggregate {
/**
* 添加商品
*/
void addGoods(Goods goods);
/**
* 删除商品
*/
void removeGoods(Goods goods);
/**
* 获取商品迭代器
*/
GoodsIterator getGoodsIterator();
}
创建具体聚合角色
/**
* @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);
}
}
创建抽象迭代器角色
/**
* @author zhh
* @description 商品抽象迭代器接口
* @date 2020-02-28 14:28
*/
public interface GoodsIterator {
/**
* 获取下一个商品
*/
Goods nextGoods();
/**
* 判断是否还有商品
*/
boolean hasGoods();
}
创建具体迭代器角色
/**
* @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;
}
}
测试类及输出
/**
* @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
类结构图
以上示例类的结构图如下所示
总结
适用场景
- 当访问一个聚合对象中的内容但又不想暴露其内部表示。
- 需要为聚合对象提供多种的遍历方式。
- 当需要为遍历不同的聚合结构提供一个统一的接口。
优点
- 具有良好的封装性,为遍历不同的聚合结构提供了一个统一的接口。
- 分离了聚合类的遍历行为,简化聚合类。
- 具有良好的扩展性,新增聚合类和迭代器类无需修改原有代码。
缺点
增加了类的个数,这在一定程度上增加了系统的复杂性。
参考
- 《Head First 设计模式》
- 《大话设计模式》
- 维基百科-迭代器模式
- 菜鸟教程-迭代器模式