在家具生产车间中,我们常常需要对生产完成的家具(如椅子、桌子、衣柜等)进行盘点、质检或入库操作。这些家具通常会暂存于一个"家具仓库"中,仓库的内部可能用数组、链表或向量等不同结构存储家具。如果每次盘点都要根据仓库的内部结构编写不同的遍历代码,不仅会暴露仓库的实现细节,还会导致代码耦合度极高。迭代器模式恰好能解决这个问题——它提供一种统一的方式遍历聚合对象(如家具仓库)中的元素,而无需暴露其内部表示。

一、迭代器模式的核心概念与角色

迭代器模式是一种行为型设计模式,其核心思想是将"遍历逻辑"与"聚合对象"分离,使两者可以独立变化。在家具生产场景中,我们可以将核心角色与实际业务对应起来:

  • 抽象迭代器(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 关键设计亮点

  1. 封装性保障:实木家具仓库的核心存储结构vector<Furniture*>是私有成员,客户端无法直接访问,只能通过迭代器间接遍历,避免了内部结构暴露。

  2. 遍历与聚合解耦:客户端遍历代码(main函数中while循环)仅依赖FurnitureIterator接口,与仓库的存储结构(vector)无关。若后续将仓库存储改为链表,只需新增适配链表的具体迭代器(如LinkedListWarehouseIterator),客户端代码无需修改。

  3. 扩展性良好:若需要新增"板式家具仓库",只需创建BoardWarehouse(实现FurnitureWarehouse)和BoardWarehouseIterator(实现FurnitureIterator),符合"开闭原则"。

3.3 迭代器模式的适用场景

1. 当需要遍历聚合对象但不想暴露其内部结构时(如家具仓库隐藏存储方式); 2. 当需要为同一聚合对象提供多种遍历方式时(如正序盘点、按材质筛选遍历); 3. 当需要统一不同聚合对象的遍历接口时(如同时遍历实木仓库和板式仓库)。

四、总结

迭代器模式通过引入独立的迭代器对象,将聚合对象的"数据存储"与"遍历逻辑"彻底分离。在家具生产场景中,它让我们无需关心仓库是用数组、向量还是链表存储家具,只需通过统一的迭代器接口即可完成盘点、质检等操作。这种设计不仅简化了客户端代码,还提升了系统的可扩展性和可维护性,是C++中集合类遍历的核心设计思想(如STL的vector、list迭代器本质就是迭代器模式的实现)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐