C++设计模式之迭代器模式:以家具生产为例
在家具生产车间中,我们常常需要对生产完成的家具(如椅子、桌子、衣柜等)进行盘点、质检或入库操作。这些家具通常会暂存于一个"家具仓库"中,仓库的内部可能用数组、链表或向量等不同结构存储家具。如果每次盘点都要根据仓库的内部结构编写不同的遍历代码,不仅会暴露仓库的实现细节,还会导致代码耦合度极高。迭代器模式恰好能解决这个问题——它提供一种统一的方式遍历聚合对象(如家具仓库)中的元素,而无需暴露其内部表示。
一、迭代器模式的核心概念与角色
迭代器模式是一种行为型设计模式,其核心思想是将"遍历逻辑"与"聚合对象"分离,使两者可以独立变化。在家具生产场景中,我们可以将核心角色与实际业务对应起来:
-
抽象迭代器(Iterator):定义遍历家具仓库的统一接口,包含判断是否有下一件家具的
hasNext()方法和获取下一件家具的next()方法。 -
具体迭代器(ConcreteIterator):实现抽象迭代器接口,记录当前遍历到的位置,针对家具仓库的具体存储结构(如向量)实现遍历逻辑。
-
抽象聚合(Aggregate):定义家具仓库的抽象接口,包含创建迭代器的
createIterator()方法和添加家具的addFurniture()方法。 -
具体聚合(ConcreteAggregate):实际的家具仓库实现,存储家具集合(如用
vector存储),并返回适配自身的具体迭代器。 -
元素(Element):遍历的对象,即家具(如椅子、桌子等,用
Furniture类表示)。
二、C++代码实现:家具仓库的迭代器遍历
我们以"实木家具仓库"为例,仓库内部用vector存储生产完成的家具,通过迭代器实现对仓库内家具的统一遍历,支持盘点时输出家具信息。
2.1 完整代码实现
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 元素:家具类(包含家具类型、型号、材质信息)
class Furniture {
private:
string type; // 家具类型(如"椅子"、"桌子")
string model; // 型号(如"实木休闲椅-001")
string material; // 材质(如"橡木"、"胡桃木")
public:
Furniture(string t, string m, string mat)
: type(t), model(m), material(mat) {}
// 打印家具信息(供遍历输出使用)
void showInfo() const {
cout << "家具类型:" << type
<< ",型号:" << model
<< ",材质:" << material << endl;
}
};
// 抽象迭代器:定义遍历家具的接口
class FurnitureIterator {
public:
virtual ~FurnitureIterator() {}
// 判断是否还有下一件家具
virtual bool hasNext() const = 0;
// 获取下一件家具
virtual Furniture* next() = 0;
};
// 抽象聚合:家具仓库的抽象接口
class FurnitureWarehouse {
public:
virtual ~FurnitureWarehouse() {}
// 添加家具到仓库
virtual void addFurniture(Furniture* furniture) = 0;
// 创建迭代器(核心方法:聚合对象提供迭代器)
virtual FurnitureIterator* createIterator() = 0;
};
// 具体迭代器:实木家具仓库迭代器(适配vector存储结构)
class SolidWoodWarehouseIterator : public FurnitureIterator {
private:
FurnitureWarehouse* warehouse; // 关联的仓库
vector<Furniture*> furnitureList; // 仓库内的家具集合(通过友元获取)
int currentIndex; // 当前遍历索引(游标)
public:
// 构造函数:初始化仓库、家具集合和索引
SolidWoodWarehouseIterator(FurnitureWarehouse* wh, vector<Furniture*> list)
: warehouse(wh), furnitureList(list), currentIndex(0) {}
// 实现hasNext:判断索引是否未超出集合大小
bool hasNext() const override {
return currentIndex < furnitureList.size();
}
// 实现next:返回当前家具并移动索引
Furniture* next() override {
if (hasNext()) {
return furnitureList[currentIndex++];
}
return nullptr; // 无更多元素时返回空
}
};
// 具体聚合:实木家具仓库(内部用vector存储家具)
class SolidWoodWarehouse : public FurnitureWarehouse {
private:
vector<Furniture*> furnitureList; // 家具存储集合(私有,不暴露给外部)
// 声明迭代器为友元,允许其访问私有集合furnitureList
friend class SolidWoodWarehouseIterator;
public:
~SolidWoodWarehouse() {
// 析构:释放家具对象内存,避免内存泄漏
for (auto& furn : furnitureList) {
delete furn;
furn = nullptr;
}
}
// 添加家具到仓库
void addFurniture(Furniture* furniture) override {
furnitureList.push_back(furniture);
}
// 创建迭代器:返回适配当前仓库的具体迭代器
FurnitureIterator* createIterator() override {
return new SolidWoodWarehouseIterator(this, furnitureList);
}
};
// 客户端:家具盘点场景(使用迭代器遍历仓库)
int main() {
// 1. 创建实木家具仓库(具体聚合)
FurnitureWarehouse* warehouse = new SolidWoodWarehouse();
// 2. 生产家具并加入仓库(模拟生产流程)
warehouse->addFurniture(new Furniture("椅子", "实木休闲椅-001", "橡木"));
warehouse->addFurniture(new Furniture("桌子", "实木餐桌-002", "胡桃木"));
warehouse->addFurniture(new Furniture("衣柜", "实木衣柜-003", "松木"));
warehouse->addFurniture(new Furniture("椅子", "实木餐椅-004", "橡木"));
// 3. 获取迭代器并遍历盘点
FurnitureIterator* iterator = warehouse->createIterator();
cout << "=== 实木家具仓库盘点结果 ===" << endl;
while (iterator->hasNext()) {
Furniture* furn = iterator->next();
furn->showInfo();
}
// 4. 释放资源
delete iterator;
delete warehouse;
return 0;
}
三、代码解析与模式优势
3.1 核心角色对应关系
|
设计模式角色 |
对应代码类 |
核心职责 |
|---|---|---|
|
抽象迭代器(Iterator) |
FurnitureIterator |
定义hasNext()和next()统一遍历接口 |
|
具体迭代器(ConcreteIterator) |
SolidWoodWarehouseIterator |
适配vector存储,通过索引实现遍历逻辑 |
|
抽象聚合(Aggregate) |
FurnitureWarehouse |
定义addFurniture()和createIterator()接口 |
|
具体聚合(ConcreteAggregate) |
SolidWoodWarehouse |
用vector存储家具,创建具体迭代器 |
|
元素(Element) |
Furniture |
存储家具具体信息,供遍历输出 |
3.2 关键设计亮点
-
封装性保障:实木家具仓库的核心存储结构
vector<Furniture*>是私有成员,客户端无法直接访问,只能通过迭代器间接遍历,避免了内部结构暴露。 -
遍历与聚合解耦:客户端遍历代码(main函数中while循环)仅依赖
FurnitureIterator接口,与仓库的存储结构(vector)无关。若后续将仓库存储改为链表,只需新增适配链表的具体迭代器(如LinkedListWarehouseIterator),客户端代码无需修改。 -
扩展性良好:若需要新增"板式家具仓库",只需创建
BoardWarehouse(实现FurnitureWarehouse)和BoardWarehouseIterator(实现FurnitureIterator),符合"开闭原则"。
3.3 迭代器模式的适用场景
1. 当需要遍历聚合对象但不想暴露其内部结构时(如家具仓库隐藏存储方式); 2. 当需要为同一聚合对象提供多种遍历方式时(如正序盘点、按材质筛选遍历); 3. 当需要统一不同聚合对象的遍历接口时(如同时遍历实木仓库和板式仓库)。
四、总结
迭代器模式通过引入独立的迭代器对象,将聚合对象的"数据存储"与"遍历逻辑"彻底分离。在家具生产场景中,它让我们无需关心仓库是用数组、向量还是链表存储家具,只需通过统一的迭代器接口即可完成盘点、质检等操作。这种设计不仅简化了客户端代码,还提升了系统的可扩展性和可维护性,是C++中集合类遍历的核心设计思想(如STL的vector、list迭代器本质就是迭代器模式的实现)。
更多推荐


所有评论(0)