C++ 迭代器模式详解

迭代器模式(Iterator Pattern)是一种行为设计模式,它提供一种方法顺序访问 一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

核心概念

设计原则

迭代器模式遵循以下设计原则:

  1. 单一职责原则:将遍历逻辑与集合分离

  2. 开闭原则:可以引入新的集合和迭代器而不修改现有代码

  3. 封装性:隐藏集合的内部实现细节

主要优点

  1. 统一接口:为不同集合提供统一的遍历方式

  2. 多遍历支持:可以同时进行多个遍历

  3. 解耦合:将集合与遍历逻辑分离

  4. 延迟遍历:支持惰性求值和按需遍历

模式结构

主要组件

  1. Iterator(迭代器接口)

    • 定义访问和遍历元素的接口
  2. ConcreteIterator(具体迭代器)

    • 实现迭代器接口

    • 跟踪当前遍历位置

  3. Aggregate(聚合接口)

    • 定义创建迭代器对象的接口
  4. ConcreteAggregate(具体聚合)

    • 实现创建迭代器的接口

    • 返回具体迭代器的实例

完整代码示例

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

// ==================== 迭代器接口 ====================
template <typename T>
class Iterator {
public:
    virtual void first() = 0;           // 重置到第一个元素
    virtual void next() = 0;            // 移动到下一个元素
    virtual bool isDone() const = 0;    // 是否遍历完成
    virtual T currentItem() const = 0;  // 获取当前元素
    virtual ~Iterator() = default;
};

// ==================== 聚合接口 ====================
template <typename T>
class Aggregate {
public:
    virtual std::unique_ptr<Iterator<T>> createIterator() = 0;
    virtual ~Aggregate() = default;
};

// ==================== 具体聚合 ====================
template <typename T>
class ConcreteAggregate : public Aggregate<T> {
    std::vector<T> items_;
    
public:
    void addItem(const T& item) {
        items_.push_back(item);
    }
    
    T getItem(size_t index) const {
        if (index >= items_.size()) {
            throw std::out_of_range("索引超出范围");
        }
        return items_[index];
    }
    
    size_t size() const {
        return items_.size();
    }
    
    std::unique_ptr<Iterator<T>> createIterator() override;
};

// ==================== 具体迭代器 ====================
template <typename T>
class ConcreteIterator : public Iterator<T> {
    const ConcreteAggregate<T>& aggregate_;
    size_t current_;
    
public:
    explicit ConcreteIterator(const ConcreteAggregate<T>& aggregate)
        : aggregate_(aggregate), current_(0) {}
    
    void first() override {
        current_ = 0;
    }
    
    void next() override {
        if (!isDone()) {
            ++current_;
        }
    }
    
    bool isDone() const override {
        return current_ >= aggregate_.size();
    }
    
    T currentItem() const override {
        if (isDone()) {
            throw std::out_of_range("迭代器已到达末尾");
        }
        return aggregate_.getItem(current_);
    }
};

// 在类外定义createIterator
template <typename T>
std::unique_ptr<Iterator<T>> ConcreteAggregate<T>::createIterator() {
    return std::make_unique<ConcreteIterator<T>>(*this);
}

// ==================== 客户端代码 ====================
int main() {
    std::cout << "=== 迭代器模式演示 ===" << std::endl;
    
    // 创建具体聚合对象
    ConcreteAggregate<std::string> aggregate;
    aggregate.addItem("第一个元素");
    aggregate.addItem("第二个元素");
    aggregate.addItem("第三个元素");
    aggregate.addItem("第四个元素");
    
    // 创建迭代器
    auto iterator = aggregate.createIterator();
    
    // 使用迭代器遍历
    std::cout << "\n正向遍历:" << std::endl;
    for (iterator->first(); !iterator->isDone(); iterator->next()) {
        std::cout << iterator->currentItem() << std::endl;
    }
    
    // 重置迭代器
    iterator->first();
    
    // 跳过第一个元素
    std::cout << "\n跳过第一个元素:" << std::endl;
    iterator->next();
    while (!iterator->isDone()) {
        std::cout << iterator->currentItem() << std::endl;
        iterator->next();
    }
    
    // 尝试访问结束后的元素
    try {
        std::cout << "\n尝试访问结束后的元素:" << std::endl;
        std::cout << iterator->currentItem() << std::endl;
    } catch (const std::out_of_range& e) {
        std::cerr << "错误: " << e.what() << std::endl;
    }
    
    return 0;
}

模式变体

1. 反向迭代器

复制代码
template <typename T>
class ReverseIterator : public Iterator<T> {
    const ConcreteAggregate<T>& aggregate_;
    size_t current_;
    
public:
    explicit ReverseIterator(const ConcreteAggregate<T>& aggregate)
        : aggregate_(aggregate), current_(aggregate.size() - 1) {}
    
    void first() override {
        current_ = aggregate_.size() - 1;
    }
    
    void next() override {
        if (!isDone()) {
            --current_;
        }
    }
    
    bool isDone() const override {
        return current_ >= aggregate_.size(); // 处理size_t下溢
    }
    
    T currentItem() const override {
        if (isDone()) {
            throw std::out_of_range("迭代器已到达开头");
        }
        return aggregate_.getItem(current_);
    }
};

// 在ConcreteAggregate中添加
std::unique_ptr<Iterator<T>> createReverseIterator() {
    return std::make_unique<ReverseIterator<T>>(*this);
}

2. 过滤迭代器

复制代码
template <typename T, typename Predicate>
class FilterIterator : public Iterator<T> {
    const ConcreteAggregate<T>& aggregate_;
    Iterator<T>& iterator_;
    Predicate predicate_;
    
public:
    FilterIterator(const ConcreteAggregate<T>& aggregate, 
                  Iterator<T>& iterator,
                  Predicate predicate)
        : aggregate_(aggregate), iterator_(iterator), predicate_(predicate) {}
    
    void first() override {
        iterator_.first();
        skipNonMatching();
    }
    
    void next() override {
        iterator_.next();
        skipNonMatching();
    }
    
    bool isDone() const override {
        return iterator_.isDone();
    }
    
    T currentItem() const override {
        return iterator_.currentItem();
    }
    
private:
    void skipNonMatching() {
        while (!iterator_.isDone() && !predicate_(iterator_.currentItem())) {
            iterator_.next();
        }
    }
};

// 使用示例
auto iterator = aggregate.createIterator();
auto isEven = [](int n) { return n % 2 == 0; };
FilterIterator<int, decltype(isEven)> filterIterator(aggregate, *iterator, isEven);

实际应用场景

  1. STL容器:C++标准库中的迭代器实现

  2. 树形结构遍历:支持不同遍历方式(前序、中序、后序)

  3. 数据库查询结果:遍历查询结果集

  4. 文件系统遍历:递归遍历目录结构

  5. 图算法:深度优先、广度优先遍历

相关推荐
byte轻骑兵9 分钟前
【Bluedroid】蓝牙HID DEVICE断开连接流程源码分析
android·c++·蓝牙·hid·bluedroid
焜昱错眩..36 分钟前
代码随想录训练营第二十一天 |589.N叉数的前序遍历 590.N叉树的后序遍历
数据结构·算法
Tisfy1 小时前
LeetCode 1550.存在连续三个奇数的数组:遍历
算法·leetcode·题解·数组·遍历
wang__123001 小时前
力扣70题解
算法·leetcode·职场和发展
菜鸟破茧计划1 小时前
滑动窗口:穿越数据的时光机
java·数据结构·算法
修修修也1 小时前
【C++】特殊类设计
开发语言·c++·特殊类·类与对象
虾球xz2 小时前
游戏引擎学习第274天:基于弹簧的动态动画
c++·学习·游戏引擎
_Itachi__2 小时前
LeetCode 热题 100 101. 对称二叉树
算法·leetcode·职场和发展
byte轻骑兵2 小时前
【C++重载操作符与转换】转换与继承
开发语言·c++
少了一只鹅2 小时前
深入理解指针(5)
java·c语言·数据结构·算法