【C++】迭代器模式

迭代器模式(Iterator Pattern)是一种【行为型】设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。这种模式将遍历逻辑封装在迭代器对象中,使客户端可以统一使用迭代器来访问不同类型的聚合对象,无需关心对象的具体实现。

一、模式核心概念与结构

迭代器模式包含四个核心角色:

  1. 迭代器接口(Iterator):定义访问和遍历元素的接口,如next()hasNext()等方法。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,跟踪聚合对象中的当前位置。
  3. 聚合接口(Aggregate):定义创建迭代器对象的接口,如createIterator()方法。
  4. 具体聚合(Concrete Aggregate):实现聚合接口,创建与之对应的具体迭代器。

二、C++ 实现示例:自定义集合迭代器

以下是一个简单的迭代器模式示例,演示如何为自定义集合实现迭代器:

#include <iostream>
#include <memory>
#include <vector>

// 前向声明
template <typename T> class Iterator;
template <typename T> class ConcreteAggregate;

// 迭代器接口
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::shared_ptr<Iterator<T>> createIterator() = 0;
};

// 具体迭代器
template <typename T>
class ConcreteIterator : public Iterator<T> {
private:
    std::shared_ptr<std::vector<T>> collection;
    size_t position;

public:
    ConcreteIterator(std::shared_ptr<std::vector<T>> coll)
        : collection(coll), position(0) {}
    
    bool hasNext() const override {
        return position < collection->size();
    }
    
    T next() override {
        if (hasNext()) {
            return (*collection)[position++];
        }
        throw std::out_of_range("No more elements");
    }
};

// 具体聚合
template <typename T>
class ConcreteAggregate : public Aggregate<T> {
private:
    std::shared_ptr<std::vector<T>> items;

public:
    ConcreteAggregate() : items(std::make_shared<std::vector<T>>()) {}
    
    void addItem(const T& item) {
        items->push_back(item);
    }
    
    std::shared_ptr<Iterator<T>> createIterator() override {
        return std::make_shared<ConcreteIterator<T>>(items);
    }
};

// 客户端代码
int main() {
    // 创建聚合对象
    auto aggregate = std::make_shared<ConcreteAggregate<std::string>>();
    aggregate->addItem("Apple");
    aggregate->addItem("Banana");
    aggregate->addItem("Cherry");
    
    // 创建迭代器
    auto iterator = aggregate->createIterator();
    
    // 使用迭代器遍历集合
    std::cout << "Items in collection:" << std::endl;
    while (iterator->hasNext()) {
        std::cout << iterator->next() << std::endl;
    }
    
    return 0;
}

三、迭代器模式的关键特性

  1. 统一遍历接口
    • 客户端通过迭代器接口访问聚合对象,无需关心其内部结构。
  2. 遍历与聚合分离
    • 迭代器将遍历逻辑从聚合对象中分离出来,使聚合对象可以专注于存储数据。
  3. 支持多种遍历方式
    • 可以为同一个聚合对象提供不同的迭代器实现,支持不同的遍历策略。
  4. 简化客户端代码
    • 客户端无需手动管理遍历状态,降低代码复杂度。

四、应用场景

  1. 访问聚合对象
    • 遍历数组、链表、树等各种数据结构。
    • 例如,遍历文件系统目录树、数据库查询结果集。
  2. 隐藏内部实现
    • 当聚合对象的内部结构复杂或不希望暴露时,使用迭代器封装访问逻辑。
  3. 支持多种遍历方式
    • 为同一聚合对象提供不同的遍历方式(如正向、反向、深度优先、广度优先)。
  4. 统一遍历接口
    • 为不同类型的聚合对象提供统一的遍历接口,简化客户端代码。

五、迭代器模式与其他设计模式的关系

  1. 组合模式
    • 迭代器模式常与组合模式一起使用,用于遍历组合结构中的元素。
    • 例如,遍历树形结构中的所有节点。
  2. 工厂模式
    • 迭代器通常由工厂方法创建,聚合对象通过工厂方法返回具体迭代器。
  3. 观察者模式
    • 当聚合对象的内容发生变化时,可以使用观察者模式通知所有迭代器。

六、C++ 标准库中的迭代器模式应用

  1. STL 迭代器
    • C++ 标准模板库(STL)广泛使用迭代器模式,如std::vectorstd::liststd::map等容器都提供迭代器。
  2. 范围 for 循环
    • C++11 引入的范围 for 循环依赖于迭代器接口,简化了容器遍历。
  3. 算法与迭代器分离
    • STL 算法(如std::findstd::sort)通过迭代器操作容器元素,实现了算法与数据结构的解耦。

七、优缺点分析

优点:

  • 解耦遍历与聚合:简化聚合类,符合单一职责原则。
  • 支持多种遍历方式:可以为同一聚合对象提供不同的迭代器。
  • 统一接口:客户端可以一致地处理不同类型的聚合对象。
  • 简化客户端代码:无需手动管理遍历状态,降低出错概率。

缺点:

  • 类数量增加:每个聚合类都需要对应的迭代器类,可能导致类膨胀。
  • 维护成本:当聚合对象的结构发生变化时,可能需要修改迭代器类。
  • 功能限制:某些特殊的遍历需求可能需要定制迭代器,增加实现复杂度。

八、实战案例:二叉树迭代器

以下是一个二叉树迭代器的实现示例,支持中序遍历:

#include <iostream>
#include <memory>
#include <stack>

// 前向声明
template <typename T> class BinaryTree;
template <typename T> class BinaryTreeIterator;

// 树节点
template <typename T>
class TreeNode {
public:
    T data;
    std::shared_ptr<TreeNode<T>> left;
    std::shared_ptr<TreeNode<T>> right;
    
    TreeNode(const T& value) : data(value), left(nullptr), right(nullptr) {}
};

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

// 二叉树迭代器(中序遍历)
template <typename T>
class BinaryTreeIterator : public Iterator<T> {
private:
    std::shared_ptr<TreeNode<T>> root;
    std::stack<std::shared_ptr<TreeNode<T>>> stack;
    std::shared_ptr<TreeNode<T>> current;

public:
    BinaryTreeIterator(std::shared_ptr<TreeNode<T>> node) : root(node) {
        // 初始化栈,将左子树压入栈
        current = root;
        while (current) {
            stack.push(current);
            current = current->left;
        }
    }
    
    bool hasNext() const override {
        return !stack.empty();
    }
    
    T next() override {
        if (!hasNext()) {
            throw std::out_of_range("No more elements");
        }
        
        // 弹出栈顶元素
        auto node = stack.top();
        stack.pop();
        
        // 处理右子树
        current = node->right;
        while (current) {
            stack.push(current);
            current = current->left;
        }
        
        return node->data;
    }
};

// 二叉树聚合类
template <typename T>
class BinaryTree {
private:
    std::shared_ptr<TreeNode<T>> root;

public:
    BinaryTree() : root(nullptr) {}
    
    void insert(const T& value) {
        root = insertRecursive(root, value);
    }
    
    std::shared_ptr<TreeNode<T>> insertRecursive(std::shared_ptr<TreeNode<T>> node, const T& value) {
        if (!node) {
            return std::make_shared<TreeNode<T>>(value);
        }
        
        if (value < node->data) {
            node->left = insertRecursive(node->left, value);
        } else if (value > node->data) {
            node->right = insertRecursive(node->right, value);
        }
        
        return node;
    }
    
    std::shared_ptr<Iterator<T>> createIterator() {
        return std::make_shared<BinaryTreeIterator<T>>(root);
    }
};

// 客户端代码
int main() {
    // 创建二叉树
    BinaryTree<int> tree;
    tree.insert(5);
    tree.insert(3);
    tree.insert(7);
    tree.insert(2);
    tree.insert(4);
    tree.insert(6);
    tree.insert(8);
    
    // 创建迭代器
    auto iterator = tree.createIterator();
    
    // 中序遍历输出
    std::cout << "In-order traversal:" << std::endl;
    while (iterator->hasNext()) {
        std::cout << iterator->next() << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

九、实现注意事项

  1. 迭代器失效
    • 当聚合对象的结构发生变化(如插入、删除元素)时,可能导致迭代器失效。
    • 需谨慎处理迭代器与聚合对象的同步问题。
  2. 并发访问
    • 在多线程环境中,需考虑迭代器的线程安全问题,可能需要同步机制。
  3. 迭代器类型
    • 可以为聚合对象提供多种迭代器(如前序、中序、后序遍历的二叉树迭代器)。
  4. 简化实现
    • 对于简单的聚合类,可以使用内部类实现迭代器,减少类的数量。

迭代器模式是 C++ 中处理集合遍历的重要工具,通过将遍历逻辑封装在迭代器中,使客户端可以统一、透明地访问不同类型的聚合对象,提高了代码的可维护性和复用性。


如果这篇文章对你有所帮助,渴望获得你的一个点赞!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OpenC++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值