迭代器模式(Iterator Pattern)

C++ 迭代器模式(Iterator Pattern)

一、模式基础概述

1.1 定义

迭代器模式属于行为型设计模式 ,提供统一遍历接口,以顺序方式访问聚合容器内所有元素,全程不对外暴露容器内部存储结构、数据组织形式。将遍历逻辑与容器存储逻辑解耦,遵循单一职责原则。

1.2 核心思想

剥离集合自身的遍历行为,单独封装迭代器对象负责元素访问;客户端仅通过标准接口遍历数据,无需关心底层是数组、链表、树形等存储结构。

1.3 设计原则

  1. 单一职责:容器负责数据存储增删,迭代器负责遍历访问
  2. 迪米特法则:隐藏内部结构,降低外部与容器耦合度
  3. 开闭原则:新增遍历方式只需新增迭代器,不改动容器代码

二、核心组成角色

角色名称 核心职责 C++ 实现形式
抽象迭代器 Iterator 声明通用遍历接口,判断是否存在下一元素、获取当前元素 抽象模板基类,纯虚函数定义接口
具体迭代器 ConcreteIterator 实现遍历接口,记录遍历游标位置,关联聚合容器,完成实际遍历 继承抽象迭代器,重写遍历方法
抽象聚合容器 Aggregate 定义创建迭代器的统一接口,规范容器基础操作 抽象基类,声明创建迭代器函数
具体聚合容器 ConcreteAggregate 存储实际元素,实现创建迭代器方法,提供元素查询、新增能力 继承抽象聚合,内部维护数据集合
客户端 Client 通过迭代器遍历元素,调用标准接口完成访问 业务调用代码、主函数

三、模式运行流程

  1. 客户端创建具体聚合容器,并向容器添加业务元素
  2. 调用容器接口生成专属迭代器实例
  3. 客户端循环调用迭代器判断接口,校验是否还有未遍历元素
  4. 存在元素则获取当前元素,并移动遍历游标
  5. 遍历结束后终止访问,整个过程不直接操作容器内部数据

四、经典业务示例:书架书籍遍历

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <memory>

// 元素实体:书籍
class Book
{
private:
    std::string bookName;
public:
    Book(std::string name) : bookName(std::move(name)) {}
    std::string getName() const
    {
        return bookName;
    }
};

// 抽象迭代器模板
template<typename T>
class Iterator
{
public:
    virtual ~Iterator() = default;
    virtual bool hasNext() const = 0;
    virtual T next() = 0;
};

// 抽象聚合容器模板
template<typename T>
class Aggregate
{
public:
    virtual ~Aggregate() = default;
    virtual std::unique_ptr<Iterator<T>> createIterator() const = 0;
    virtual void addElement(const T& elem) = 0;
    virtual int getSize() const = 0;
    virtual T getElement(int index) const = 0;
};

// 具体容器:书架
class BookShelf : public Aggregate<Book>
{
private:
    std::vector<Book> bookList;
public:
    void addElement(const Book& elem) override
    {
        bookList.push_back(elem);
    }

    int getSize() const override
    {
        return bookList.size();
    }

    Book getElement(int index) const override
    {
        return bookList[index];
    }

    std::unique_ptr<Iterator<Book>> createIterator() const override;
};

// 具体迭代器:书架迭代器
class BookShelfIterator : public Iterator<Book>
{
private:
    const BookShelf* shelf;
    int currentIndex;
public:
    BookShelfIterator(const BookShelf* shelfObj)
        : shelf(shelfObj), currentIndex(0) {}

    bool hasNext() const override
    {
        return currentIndex < shelf->getSize();
    }

    Book next() override
    {
        return shelf->getElement(currentIndex++);
    }
};

// 容器绑定迭代器
std::unique_ptr<Iterator<Book>> BookShelf::createIterator() const
{
    return std::make_unique<BookShelfIterator>(this);
}

// 客户端调用
int main()
{
    BookShelf shelf;
    shelf.addElement(Book("C++设计模式"));
    shelf.addElement(Book("数据结构与算法"));
    shelf.addElement(Book("Linux编程实战"));

    auto iterator = shelf.createIterator();
    std::cout << "书架内书籍列表:\n";
    while (iterator->hasNext())
    {
        Book book = iterator->next();
        std::cout << book.getName() << std::endl;
    }
    return 0;
}

五、通用模板示例:自定义任务容器遍历

cpp 复制代码
#include <iostream>
#include <vector>
#include <memory>

// 通用抽象迭代器
template<typename T>
class BaseIterator
{
public:
    virtual ~BaseIterator() = default;
    virtual bool existNext() = 0;
    virtual T fetchNext() = 0;
};

// 通用抽象容器
template<typename T>
class BaseContainer
{
public:
    virtual ~BaseContainer() = default;
    virtual std::unique_ptr<BaseIterator<T>> getIterator() = 0;
    virtual void append(const T& data) = 0;
    virtual size_t getLength() const = 0;
    virtual T getData(size_t idx) const = 0;
};

// 线性存储容器
template<typename T>
class LinearContainer : public BaseContainer<T>
{
private:
    std::vector<T> dataArr;
public:
    void append(const T& data) override
    {
        dataArr.push_back(data);
    }

    size_t getLength() const override
    {
        return dataArr.size();
    }

    T getData(size_t idx) const override
    {
        return dataArr[idx];
    }

    std::unique_ptr<BaseIterator<T>> getIterator() override;
};

// 线性容器迭代器
template<typename T>
class LinearIterator : public BaseIterator<T>
{
private:
    LinearContainer<T>* container;
    size_t cursor;
public:
    LinearIterator(LinearContainer<T>* con) : container(con), cursor(0) {}

    bool existNext() override
    {
        return cursor < container->getLength();
    }

    T fetchNext() override
    {
        return container->getData(cursor++);
    }
};

template<typename T>
std::unique_ptr<BaseIterator<T>> LinearContainer<T>::getIterator()
{
    return std::make_unique<LinearIterator<T>>(this);
}

// 测试使用
int main()
{
    LinearContainer<std::string> taskContainer;
    taskContainer.append("路径规划");
    taskContainer.append("环境检测");
    taskContainer.append("设备自检");

    auto iter = taskContainer.getIterator();
    std::cout << "\n机器人任务清单:\n";
    while (iter->existNext())
    {
        std::cout << iter->fetchNext() << std::endl;
    }
    return 0;
}

六、迭代器分类说明

  1. 外部迭代器
    客户端主动控制遍历启停、游标移动,日常开发最常用。
  2. 内部迭代器
    迭代器自身完成全部遍历逻辑,客户端仅发起遍历请求。
  3. 正向迭代器
    仅支持从头部向尾部单向遍历。
  4. 双向迭代器
    可前后移动游标,支持正反遍历元素。
  5. 随机访问迭代器
    支持下标取值、游标跳跃访问,访问效率最高。

七、与C++ STL迭代器关联

STL容器遍历是迭代器模式工业化落地实现

  1. begin()end() 等同于创建迭代器对象
  2. ++-- 运算符实现游标移动
  3. * 解引用运算符获取容器元素
  4. 统一遍历接口,vector、list、map可复用遍历代码
cpp 复制代码
#include <iostream>
#include <vector>
int main()
{
    std::vector<int> numVec = {10,20,30,40};
    // STL标准迭代器用法
    for (auto it = numVec.begin(); it != numVec.end(); ++it)
    {
        std::cout << *it << " ";
    }
    return 0;
}

八、模式优缺点

8.1 优点

  1. 统一遍历接口,适配多种异构容器,遍历代码可复用
  2. 屏蔽容器底层存储细节,提升数据安全性
  3. 存储与遍历职责拆分,代码结构清晰易维护
  4. 可同时创建多个迭代器,并行遍历同一容器
  5. 灵活扩展遍历方式,正序、倒序、过滤遍历互不影响

8.2 缺点

  1. 每新增一种容器,需配套编写对应迭代器类,类数量增加
  2. 极简小型集合使用该模式,存在代码冗余、过度设计
  3. 遍历过程中修改容器结构,容易引发迭代器失效问题

九、适用业务场景

  1. 项目存在多种不同存储结构的集合,需要统一遍历方式
  2. 要求隐藏容器内部数据组织,禁止外部直接访问底层结构
  3. 同一集合需要提供多种遍历规则、访问顺序
  4. 分离数据存储与遍历逻辑,降低模块间耦合
  5. 任务队列、数据集、地图节点、日志条目遍历场景

十、相近模式区分

模式 核心作用 侧重点
迭代器模式 统一访问集合元素 容器遍历、隐藏内部结构
组合模式 统一处理树形整体与节点 层级递归遍历对象
访问者模式 在不修改类前提下新增操作 对元素执行自定义业务操作

十一、C++工程编码规范

  1. 使用std::unique_ptr管理迭代器实例,自动回收内存
  2. 迭代器仅做元素访问,不修改容器内部数据与结构
  3. 遍历周期内避免增删元素,防止迭代器失效崩溃
  4. 常规业务优先使用STL原生迭代器,自定义特殊容器再手写迭代器
  5. 抽象接口精简通用,保证不同迭代器调用规则一致

十二、模式总结

迭代器模式核心是访问分离、结构隐藏、接口统一

通过独立迭代器接管遍历逻辑,让容器专注数据存储,客户端以通用方式读取元素,无需感知底层实现。该模式是C++容器体系的基础设计思想,广泛应用于数据遍历、任务处理、集合管理等业务场景,有效简化多容器兼容开发成本。

相关推荐
程序员mine3 天前
HTTPS-TLS加密与证书完全指南(中)
网络协议·https·ssl
之歆3 天前
现代 HTTP 客户端深度解析:Fetch 与 Axios
chrome·网络协议·http
小胖xiaopangss3 天前
BRpc使用
c++·rpc
酉鬼女又兒3 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog2503 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
程序员mine3 天前
HTTPS-TLS加密与证书完全指南(上)
网络协议·https
VidDown3 天前
视频帧率技术详解:从 24fps 到 120fps,帧率如何影响你的观看体验?
网络·网络协议·编辑器·音视频·视频编解码·视频
程序员mine3 天前
HTTPS-TLS加密与证书完全指南(下)
网络协议·http·https
zhuzicc3 天前
Dubbo @Autowired 注入同模块接口,到底走的是本地调用还是 RPC?源码给你答案(Dubbo @Service注解的双重注册机制)
rpc·autowired·dubbo·依赖注入·java面试·spring ioc·dubbo源码分析
hbugs0013 天前
EVE-NG V7常用网络协议流量洞察Filter
网络·网络协议