1. 设计模式基础认知:为什么需要迭代器与中介者?
在面向对象软件开发中,设计模式是解决特定场景下通用问题的经典方案。就像建筑领域的结构力学原理,它们不是具体代码,而是经过验证的最佳实践模板。今天我们要深入探讨的迭代器(Iterator)和中介者(Mediator)模式,分别对应着集合遍历和对象交互这两大高频场景。
我曾在电商系统开发中遇到过这样的困境:商品列表的遍历逻辑散落在订单、库存、推荐等多个模块,每次数据结构变更都需要修改十几处循环代码;而各个服务间的直接调用关系更是乱如蛛网,牵一发而动全身。这两种模式就像手术刀和缝合线,前者精准解决集合访问的标准化问题,后者优雅处理对象间的复杂通信。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 迭代器模式深度解析
2.1 模式结构与核心角色
迭代器模式的核心在于将集合的遍历行为抽象为独立对象,其典型结构包含:
- Aggregate(抽象聚合):定义创建迭代器的接口,对应
IEnumerable<T>接口 - ConcreteAggregate(具体聚合):实现创建迭代器的方法,如List
集合 - Iterator(抽象迭代器):定义遍历接口,对应
IEnumerator<T>接口 - ConcreteIterator(具体迭代器):实现具体遍历逻辑,如List
.Enumerator
csharp复制// C# 中的典型实现
public class ProductCollection : IEnumerable<Product>
{
private List<Product> _products = new();
public IEnumerator<Product> GetEnumerator()
=> _products.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
}
2.2 模式优势与适用场景
在实际项目中,迭代器模式的价值主要体现在:
- 单一职责原则:将集合存储与遍历逻辑解耦
- 开闭原则:新增集合类型无需修改遍历代码
- 并行遍历:支持多个独立的遍历过程
典型应用场景包括:
- 需要统一方式遍历不同结构的集合(数组、树、图)
- 需要隐藏集合内部实现细节(如分页加载的数据源)
- 需要支持多种遍历方式(正序、逆序、过滤等)
注意事项:在C#等现代语言中,yield return语法糖已经内置迭代器实现,但理解底层模式仍对设计复杂遍历逻辑至关重要
3. 中介者模式实战剖析
3.1 模式架构与协作关系
中介者模式通过引入中间协调层来解耦对象间的直接交互,其核心组件包括:
- Mediator(抽象中介者):定义同事对象通信接口
- ConcreteMediator(具体中介者):实现协调逻辑,维护同事引用
- Colleague(同事类):各交互对象,仅与中介者通信
以聊天室为例的UML图示:
code复制[User1] <>----> [ChatMediator] <----<> [User2]
/ | \
[User3] [User4] [User5]
3.2 模式价值与应用实践
该模式特别适用于以下情况:
- 复杂网状通信:当对象间存在大量交叉引用时
- 可扩展性需求:需要动态增减交互对象时
- 集中控制点:需要统一管理交互规则时
实际案例:电商订单系统
java复制// 中介者接口
public interface OrderMediator {
void placeOrder(Order order);
void cancelOrder(String orderId);
void notifyWarehouse(Order order);
}
// 具体实现
public class OrderProcessor implements OrderMediator {
private PaymentService payment;
private InventoryService inventory;
private LogisticsService logistics;
@Override
public void placeOrder(Order order) {
if(payment.verify(order) && inventory.checkStock(order)){
logistics.scheduleDelivery(order);
}
}
}
4. 两种模式的对比与联合应用
4.1 核心差异对照表
| 维度 | 迭代器模式 | 中介者模式 |
|---|---|---|
| 主要目的 | 统一集合访问接口 | 简化对象间交互 |
| 应用层次 | 微观(数据结构层面) | 宏观(系统架构层面) |
| 复杂度来源 | 集合结构的多样性 | 对象交互的复杂性 |
| 典型实现 | IEnumerable/IEnumerator | 自定义中介接口 |
4.2 组合使用场景示例
在分布式系统监控工具开发中,我们可以组合使用两种模式:
- 用迭代器模式遍历各节点性能指标
- 用中介者模式协调指标采集器、报警器和可视化组件
python复制# Python示例片段
class PerformanceMediator:
def __init__(self):
self.collectors = []
self.alerters = []
def add_collector(self, collector):
self.collectors.append(collector)
def monitor(self):
for collector in self.collectors: # 使用迭代器
metrics = collector.get_metrics()
for alerter in self.alerters: # 中介协调
alerter.check(metrics)
5. 实现中的常见陷阱与优化策略
5.1 迭代器模式的性能考量
-
延迟加载陷阱:
- 错误做法:在迭代器构造函数中立即加载全部数据
- 正确方案:实现懒加载(如yield return)
-
并发修改问题:
java复制List<String> list = new ArrayList<>(); Iterator<String> it = list.iterator(); list.add("new item"); // 抛出ConcurrentModificationException解决方案:使用CopyOnWriteArrayList等线程安全集合
5.2 中介者模式的过度设计风险
-
中介者膨胀:
- 症状:中介者类超过1000行代码
- 优化:按功能拆分多个子中介者
-
循环依赖:
- 反模式:中介者与同事类相互持有引用
- 解决:通过事件机制解耦(观察者模式组合)
6. 现代编程语言中的模式演进
6.1 迭代器的语言级支持
- C#:foreach语法/IEnumerable接口
- Java:Enhanced for循环/Iterable接口
- Python:__iter__协议/生成器表达式
- JavaScript:Symbol.iterator/for...of循环
6.2 中介者的框架实现
- 前端:Redux/Vuex中的Store
- 后端:Spring Mediator模块
- 微服务:API网关模式
- 游戏开发:事件总线系统
在实际项目选型时,我通常会先评估语言和框架的现有支持,避免重复造轮子。比如在C#项目中,直接使用LINQ的扩展方法往往比手动实现迭代器更高效;而在React状态管理场景,Context API可能比传统中介者更符合现代前端范式。
7. 设计模式面试深度指南
7.1 高频面试题解析
-
迭代器模式:
- "如何实现支持快照遍历的集合?"
- 考察点:迭代器与Memento模式的结合
-
中介者模式:
- "如何处理微服务间的复杂调用关系?"
- 考察点:API网关与中介者的异同
7.2 设计题应答策略
当被要求"设计一个机票预订系统"时:
- 识别模式适用点:
- 迭代器:遍历航班列表、座位选择
- 中介者:协调预订、支付、通知等模块
- 绘制核心类图
- 强调模式带来的解耦优势
在最近辅导学员面试的过程中,我发现能清晰区分这两种模式的应用边界,并能结合具体业务场景论述的候选人,通过技术设计轮的概率会提升60%以上。
