摘要
本文详细介绍了迭代器设计模式,这是一种行为型设计模式,用于顺序访问集合对象中的元素,同时隐藏集合的内部结构。文章首先定义了迭代器设计模式并阐述了其核心角色,包括迭代器接口、具体迭代器、容器接口和具体容器。接着,文章通过 Java 标准库中的 Iterator 接口为例,展示了迭代器设计模式的结构和实现方式。此外,文章还探讨了迭代器设计模式的适用场景,包括适合和不适合使用该模式的情况,并通过金融风控的实战示例,展示了如何将迭代器设计模式与其他设计模式(如责任链模式、策略模式等)结合使用。最后,文章总结了迭代器设计模式与其他设计模式的组合使用方式。
1. 迭代器设计模式定义
迭代器设计模式(Iterator Pattern)是一种行为型设计模式,用于顺序访问一个集合对象中的元素,而又不暴露该对象的内部表示结构。
1.1. 🔹 核心角色:
角色 | 说明 |
Iterator(迭代器接口) | 定义访问和遍历元素的接口,如 |
ConcreteIterator(具体迭代器) | 实现 |
Aggregate(容器接口) | 定义创建迭代器对象的方法。 |
ConcreteAggregate(具体容器) | 实现 |
Java 标准库中广泛使用了该模式,例如 java.util.Iterator
接口就是该模式的典型实现。
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
2. 迭代器设计模式结构
- 迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
- 具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
- 集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
- 具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。
- 客户端 (Client) 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。客户端通常不会自行创建迭代器, 而是会从集合中获取。 但在特定情况下, 客户端可以直接创建一个迭代器 (例如当客户端需要自定义特殊迭代器时)。
2.1. 迭代器类图
2.2. 迭代器时序图
3. 迭代器设计模式实现方式
迭代器设计模式的实现方式主要包括自定义以下四个关键角色:容器接口、具体容器、迭代器接口、具体迭代器。下面是标准的实现步骤(以 Java 为例)。
3.1. 🔹 定义迭代器接口 Iterator
public interface Iterator<T> {
boolean hasNext();
T next();
}
3.2. 🔹 定义聚合容器接口 Aggregate
public interface Aggregate<T> {
Iterator<T> createIterator();
}
3.3. 🔹 实现具体容器 ConcreteAggregate
public class ConcreteAggregate<T> implements Aggregate<T> {
private List<T> items = new ArrayList<>();
public void add(T item) {
items.add(item);
}
public T get(int index) {
return items.get(index);
}
public int size() {
return items.size();
}
@Override
public Iterator<T> createIterator() {
return new ConcreteIterator<>(this);
}
}
3.4. 🔹 实现具体迭代器 ConcreteIterator
public class ConcreteIterator<T> implements Iterator<T> {
private ConcreteAggregate<T> aggregate;
private int currentIndex = 0;
public ConcreteIterator(ConcreteAggregate<T> aggregate) {
this.aggregate = aggregate;
}
@Override
public boolean hasNext() {
return currentIndex < aggregate.size();
}
@Override
public T next() {
return aggregate.get(currentIndex++);
}
}
3.5. 🔹 使用示例
public class Main {
public static void main(String[] args) {
ConcreteAggregate<String> container = new ConcreteAggregate<>();
container.add("A");
container.add("B");
container.add("C");
Iterator<String> iterator = container.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
3.6. ✅ 迭代器示例总结
组件 | 作用 |
| 提供统一遍历接口 |
| 维护当前索引、实现遍历逻辑 |
| 提供创建迭代器方法 |
| 存储数据集合,并生成迭代器 |
4. 迭代器设计模式适合场景
迭代器设计模式的核心目的是提供统一的遍历接口,屏蔽容器内部的数据结构差异。下面是它适合与不适合的场景分析:
4.1. ✅ 适合使用迭代器设计模式的场景
场景 | 说明 |
✅ 容器类集合遍历 | 当你希望对集合(数组、列表、树、图等)进行遍历,不暴露其内部结构。 |
✅ 多种容器结构共用遍历方式 | 例如支持 |
✅ 需要多种遍历方式 | 如顺序、逆序、跳跃等不同的遍历策略,可以封装成不同的迭代器类。 |
✅ 自定义复杂聚合对象遍历 | 比如订单->商品->商品属性 这种层级结构,可以通过迭代器隐藏细节,统一接口。 |
✅ 希望解耦容器与遍历逻辑 | 把“遍历逻辑”从容器中抽离出来,符合单一职责、开闭原则。 |
✅ 支持多并发遍历操作 | 每个迭代器对象互不干扰,可以实现并发读操作。 |
4.2. ❌ 不适合使用迭代器设计模式的场景
场景 | 原因 |
❌ 集合结构非常简单,且不会改变 | 比如只有 1~2 个元素,直接使用 for-each 更高效,没必要引入额外迭代器类。 |
❌ 对遍历性能要求极高的系统(高频大数据处理) | 自定义迭代器层级增加方法调用,可能影响性能,如在实时交易撮合、低延迟系统中。 |
❌ 对象间耦合必须最小,不能增加接口依赖 | 引入 |
❌ 需要对遍历过程进行复杂控制(如跳转、回溯) | 此时可能更适合状态机模式或访问者模式,对每一步状态进行更复杂管理。 |
❌ 遍历逻辑需要携带大量上下文或中间状态 | 简单的迭代器不适合包含太多状态持久性,需要扩展为上下文感知处理器模式。 |
4.3. ✅ 举个金融风控例子
适合:遍历用户的多个信用卡账户,统一处理风控评分。
for (Account account : userAccountIterator) {
scoreService.evaluate(account);
}
不适合:实时交易撮合引擎中,大量订单队列需要毫秒级处理,使用数组/队列遍历更高效,不宜引入自定义迭代器。
5. 迭代器设计模式实战示例
下面是一个在金融风控场景下,使用迭代器设计模式 + Spring 注解注入方式 实现的示例,适合处理多个风控规则依次执行的业务逻辑。
5.1. 🎯 场景描述
对信贷申请进行风控判断。每个申请会通过一系列规则(如黑名单、年龄检查、信用分检查),每条规则是一个策略,同时这些策略按顺序组成一个责任链。为了支持动态控制规则顺序,还使用迭代器遍历规则链。
5.2. ☕️ 项目结构
com.example.risk
├── RiskRule.java # 策略接口
├── AbstractRiskRule.java # 模板实现
├── BlackListRule.java # 黑名单规则
├── AgeLimitRule.java # 年龄限制规则
├── CreditScoreRule.java # 信用分规则
├── RuleChainContext.java # 责任链 + 迭代器控制
├── RiskRequest.java # 入参
├── RiskResponse.java # 出参
├── RuleConfig.java # 自动注入规则列表
└── RiskService.java # 风控服务入口
5.3. 风控请求/响应对象
@Data
public class RiskRequest {
private String userId;
private int age;
private int creditScore;
private boolean inBlackList;
}
@Data
public class RiskResponse {
private boolean passed = true;
private String failedReason;
}
5.4. 策略接口和抽象类(策略 + 模板)
public interface RiskRule {
boolean evaluate(RiskRequest request, RiskResponse response);
String getName();
}
public abstract class AbstractRiskRule implements RiskRule {
@Override
public boolean evaluate(RiskRequest request, RiskResponse response) {
if (!doEvaluate(request)) {
response.setPassed(false);
response.setFailedReason(getName());
return false;
}
return true;
}
protected abstract boolean doEvaluate(RiskRequest request);
}
5.5. 各种规则实现(策略 + 责任链)
@Component
public class BlackListRule extends AbstractRiskRule {
@Override
public String getName() {
return "黑名单规则";
}
@Override
protected boolean doEvaluate(RiskRequest request) {
return !request.isInBlackList();
}
}
@Component
public class AgeLimitRule extends AbstractRiskRule {
@Override
public String getName() {
return "年龄限制规则";
}
@Override
protected boolean doEvaluate(RiskRequest request) {
return request.getAge() >= 18;
}
}
@Component
public class CreditScoreRule extends AbstractRiskRule {
@Override
public String getName() {
return "信用分规则";
}
@Override
protected boolean doEvaluate(RiskRequest request) {
return request.getCreditScore() >= 600;
}
}
5.6. RuleChainContext(责任链 + 迭代器)
@Component
public class RuleChainContext {
private final List<RiskRule> ruleList;
@Autowired
public RuleChainContext(List<RiskRule> ruleList) {
// 可排序或通过配置动态控制顺序
this.ruleList = ruleList;
}
public RiskResponse process(RiskRequest request) {
RiskResponse response = new RiskResponse();
Iterator<RiskRule> iterator = ruleList.iterator();
while (iterator.hasNext()) {
// 迭代器进行遍历
RiskRule rule = iterator.next();
if (!rule.evaluate(request, response)) {
break; // 短路失败
}
}
return response;
}
}
5.7. Service调用入口
@Service
public class RiskService {
@Autowired
private RuleChainContext ruleChainContext;
public RiskResponse evaluate(RiskRequest request) {
return ruleChainContext.process(request);
}
}
5.8. ✅ 使用方式示例
@RestController
@RequestMapping("/risk")
public class RiskController {
@Autowired
private RiskService riskService;
@PostMapping("/check")
public RiskResponse check(@RequestBody RiskRequest request) {
return riskService.evaluate(request);
}
}
5.9. 🧠 总结:设计模式用法回顾
模式 | 用法说明 |
策略模式 | 每一个规则都是一个策略,实现 |
责任链模式 | 所有规则顺序执行,遇到失败立即终止 |
迭代器模式 | 通过 |
模板方法模式 | 抽象类定义执行流程,子类重写核心判断逻辑 |
注解注入 | 使用 |
如需添加动态配置规则链顺序、启用规则开关、分组规则集等功能,可以进一步引入配置中心或数据库控制,支持高扩展。
6. 迭代器设计模式思考
6.1. 🔁 常与迭代器组合使用的设计模式
在实战开发中,迭代器设计模式(Iterator Pattern)通常与以下几种设计模式组合使用,以增强集合结构的灵活性、扩展性、解耦性,尤其在领域模型、规则处理、任务调度等系统中非常常见:
组合模式 | 搭配原因/典型场景 |
责任链模式 | 顺序执行规则或任务链,迭代器负责链路遍历 |
策略模式 | 每个元素是一个策略(如规则或算法),通过迭代器遍历并执行 |
组合模式 | 组合结构的子元素通过迭代器统一遍历(如树状结构遍历) |
模板方法模式 | 元素结构统一,遍历时调用公共模板方法,保留定制扩展点 |
观察者模式 | 遍历一组观察者并触发通知 |
命令模式 | 遍历一组命令并逐一执行(或回滚) |
装饰器模式 | 每一层装饰器通过迭代器包装组合 |
工厂方法模式 | 工厂批量创建可遍历的对象集合 |
6.1.1. 与责任链模式
场景:规则引擎、风控审核、流程编排
- 每个 handler/规则实现
RuleHandler
接口 - 用
List<RuleHandler>
通过迭代器逐个执行,遇失败中断
for (RuleHandler handler : handlers) {
if (!handler.handle(context)) {
break;
}
}
6.1.2. 与策略模式
场景:算法选择、数据转换器、规则过滤器
- 每个元素是一个策略类(如计算利息、折扣策略)
- 迭代器控制策略的执行顺序,支持动态扩展
6.1.3. 与组合模式
场景:菜单树、组织结构、数据表头嵌套结构
- 组合结构的节点可以通过迭代器实现统一的遍历
6.1.4. 与模板方法模式
场景:日志采集、批量数据导出、统一操作步骤
- 各子类复用固定遍历结构,通过
doXXX()
定制操作逻辑
6.1.5. 与命令模式
场景:批量命令处理、回滚事务、脚本执行
- 一组命令对象放入集合,通过迭代器逐个执行或撤销
模式组合 | 是否常见 | 典型用途 |
迭代器 + 责任链 | ✅ | 流程控制、规则判断 |
迭代器 + 策略 | ✅ | 动态决策执行、多策略适配 |
迭代器 + 组合 | ✅ | 树形结构统一遍历 |
迭代器 + 模板方法 | ✅ | 标准流程 + 扩展处理 |
迭代器 + 命令 | ✅ | 操作回放、事务控制 |
迭代器 + 观察者 | 🟡 | 通知一组监听者 |
迭代器 + 单例等 | ❌ | 不适合,与集合行为无关 |
博文参考
- 迭代器设计模式
- 设计模式——迭代器设计模式(行为型)