设计模式——迭代器设计模式(行为型)

摘要

本文详细介绍了迭代器设计模式,这是一种行为型设计模式,用于顺序访问集合对象中的元素,同时隐藏集合的内部结构。文章首先定义了迭代器设计模式并阐述了其核心角色,包括迭代器接口、具体迭代器、容器接口和具体容器。接着,文章通过 Java 标准库中的 Iterator 接口为例,展示了迭代器设计模式的结构和实现方式。此外,文章还探讨了迭代器设计模式的适用场景,包括适合和不适合使用该模式的情况,并通过金融风控的实战示例,展示了如何将迭代器设计模式与其他设计模式(如责任链模式、策略模式等)结合使用。最后,文章总结了迭代器设计模式与其他设计模式的组合使用方式。

1. 迭代器设计模式定义

迭代器设计模式(Iterator Pattern)是一种行为型设计模式,用于顺序访问一个集合对象中的元素,而又不暴露该对象的内部表示结构

1.1. 🔹 核心角色:

角色

说明

Iterator(迭代器接口)

定义访问和遍历元素的接口,如 hasNext()next()

ConcreteIterator(具体迭代器)

实现 Iterator接口,维护当前遍历位置。

Aggregate(容器接口)

定义创建迭代器对象的方法。

ConcreteAggregate(具体容器)

实现 Aggregate接口,返回该容器的迭代器。

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. 迭代器设计模式结构

  1. 迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
  2. 具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
  3. 集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
  4. 具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。
  5. 客户端 (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. ✅ 迭代器示例总结

组件

作用

Iterator 接口

提供统一遍历接口

ConcreteIterator

维护当前索引、实现遍历逻辑

Aggregate接口

提供创建迭代器方法

ConcreteAggregate

存储数据集合,并生成迭代器

4. 迭代器设计模式适合场景

迭代器设计模式的核心目的是提供统一的遍历接口,屏蔽容器内部的数据结构差异。下面是它适合与不适合的场景分析:

4.1. ✅ 适合使用迭代器设计模式的场景

场景

说明

容器类集合遍历

当你希望对集合(数组、列表、树、图等)进行遍历,不暴露其内部结构。

多种容器结构共用遍历方式

例如支持 ListSetMap、自定义集合类都实现一个标准的迭代器接口,便于切换。

需要多种遍历方式

如顺序、逆序、跳跃等不同的遍历策略,可以封装成不同的迭代器类。

自定义复杂聚合对象遍历

比如订单->商品->商品属性 这种层级结构,可以通过迭代器隐藏细节,统一接口。

希望解耦容器与遍历逻辑

把“遍历逻辑”从容器中抽离出来,符合单一职责、开闭原则。

支持多并发遍历操作

每个迭代器对象互不干扰,可以实现并发读操作。

4.2. ❌ 不适合使用迭代器设计模式的场景

场景

原因

集合结构非常简单,且不会改变

比如只有 1~2 个元素,直接使用 for-each 更高效,没必要引入额外迭代器类。

对遍历性能要求极高的系统(高频大数据处理)

自定义迭代器层级增加方法调用,可能影响性能,如在实时交易撮合、低延迟系统中。

对象间耦合必须最小,不能增加接口依赖

引入 Iterator接口会额外增加模块之间依赖,不符合某些架构设计原则。

需要对遍历过程进行复杂控制(如跳转、回溯)

此时可能更适合状态机模式或访问者模式,对每一步状态进行更复杂管理。

遍历逻辑需要携带大量上下文或中间状态

简单的迭代器不适合包含太多状态持久性,需要扩展为上下文感知处理器模式。

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. 🧠 总结:设计模式用法回顾

模式

用法说明

策略模式

每一个规则都是一个策略,实现 RiskRule接口

责任链模式

所有规则顺序执行,遇到失败立即终止

迭代器模式

通过 Iterator<RiskRule>遍历所有策略规则

模板方法模式

抽象类定义执行流程,子类重写核心判断逻辑

注解注入

使用 @Component+ @Autowired实现 Spring 自动装配

如需添加动态配置规则链顺序、启用规则开关、分组规则集等功能,可以进一步引入配置中心或数据库控制,支持高扩展。

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. 与命令模式

场景:批量命令处理、回滚事务、脚本执行

  • 一组命令对象放入集合,通过迭代器逐个执行或撤销

模式组合

是否常见

典型用途

迭代器 + 责任链

流程控制、规则判断

迭代器 + 策略

动态决策执行、多策略适配

迭代器 + 组合

树形结构统一遍历

迭代器 + 模板方法

标准流程 + 扩展处理

迭代器 + 命令

操作回放、事务控制

迭代器 + 观察者

🟡

通知一组监听者

迭代器 + 单例等

不适合,与集合行为无关

博文参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庄小焱

我将坚持分享更多知识

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值