【第22节】C++设计模式(行为模式)-Iterator(迭代器)模式

一、问题背景

Iterator 模式是设计模式中最为常见和实用的模式之一。它的核心思想是将对聚合对象的遍历操作封装到一个独立的类中,从而避免暴露聚合对象的内部表示。通过 Iterator 模式,我们可以实现对聚合对象的统一遍历接口,而不需要关心聚合对象的具体实现细节。

在实际开发中,Iterator 模式的应用非常广泛。例如,在实现 Composite 模式、Flyweight 模式、Observer 模式时,我们经常会使用 STL 提供的 Iterator 来遍历 `Vector` 或 `List` 等数据结构。Iterator 模式不仅简化了遍历操作,还提高了代码的可维护性和可扩展性。

二、模式选择

Iterator 模式的典型结构图如下:

在 Iterator 模式中,主要包含以下几个角色:

(1)Aggregate(聚合):定义创建 Iterator 对象的接口。

(2)ConcreteAggregate(具体聚合):实现 Aggregate 接口,返回一个具体的 Iterator 实例。

(3)Iterator(迭代器):定义遍历聚合对象的接口。

(4)ConcreteIterator(具体迭代器):实现 Iterator 接口,负责遍历具体的聚合对象。

通过这种设计,Iterator 模式将聚合对象的遍历逻辑与其内部实现分离,使得聚合对象可以独立于遍历逻辑进行修改。

三、代码实现

下面我们将通过一个完整的 C++ 代码示例来展示如何实现 Iterator 模式。为了方便初学者的学习和参考,代码将包含详细的注释。

代码片段 1:Aggregate.h

cpp 复制代码
// Aggregate.h
#ifndef _AGGREGATE_H_
#define _AGGREGATE_H_

class Iterator;
typedef int Object;  // 定义聚合对象中存储的数据类型

// Aggregate 类:定义创建 Iterator 对象的接口
class Aggregate {
public:
    virtual ~Aggregate();
    virtual Iterator* CreateIterator() = 0;  // 创建迭代器
    virtual Object GetItem(int idx) = 0;     // 获取指定位置的元素
    virtual int GetSize() = 0;               // 获取聚合对象的大小
protected:
    Aggregate();
private:
};

// ConcreteAggregate 类:具体聚合类,实现 Aggregate 接口
class ConcreteAggregate : public Aggregate {
public:
    enum { SIZE = 3 };  // 定义聚合对象的大小
    ConcreteAggregate();
    ~ConcreteAggregate();
    Iterator* CreateIterator();  // 创建迭代器
    Object GetItem(int idx);     // 获取指定位置的元素
    int GetSize();               // 获取聚合对象的大小
protected:
private:
    Object _objs[SIZE];  // 聚合对象中存储的数据
};

#endif //~_AGGREGATE_H_

代码片段 2:Aggregate.cpp

cpp 复制代码
// Aggregate.cpp
#include "Aggregate.h"
#include "Iterator.h"
#include <iostream>
using namespace std;

// Aggregate 类的实现
Aggregate::Aggregate() {
    // 构造函数
}

Aggregate::~Aggregate() {
    // 析构函数
}

// ConcreteAggregate 类的实现
ConcreteAggregate::ConcreteAggregate() {
    // 初始化聚合对象中的数据
    for (int i = 0; i < SIZE; i++) {
        _objs[i] = i;
    }
}

ConcreteAggregate::~ConcreteAggregate() {
    // 析构函数
}

Iterator* ConcreteAggregate::CreateIterator() {
    // 创建具体的迭代器对象
    return new ConcreteIterator(this);
}

Object ConcreteAggregate::GetItem(int idx) {
    // 获取指定位置的元素
    if (idx < this->GetSize()) {
        return _objs[idx];
    } else {
        return -1;  // 如果索引越界,返回 -1
    }
}

int ConcreteAggregate::GetSize() {
    // 获取聚合对象的大小
    return SIZE;
}

代码片段 3:Iterator.h

cpp 复制代码
// Iterator.h
#ifndef _ITERATOR_H_
#define _ITERATOR_H_

class Aggregate;
typedef int Object;  // 定义聚合对象中存储的数据类型

// Iterator 类:定义遍历聚合对象的接口
class Iterator {
public:
    virtual ~Iterator();
    virtual void First() = 0;          // 将迭代器指向第一个元素
    virtual void Next() = 0;           // 将迭代器指向下一个元素
    virtual bool IsDone() = 0;         // 判断是否遍历结束
    virtual Object CurrentItem() = 0;  // 获取当前元素
protected:
    Iterator();
private:
};

// ConcreteIterator 类:具体迭代器类,实现 Iterator 接口
class ConcreteIterator : public Iterator {
public:
    ConcreteIterator(Aggregate* ag, int idx = 0);  // 构造函数
    ~ConcreteIterator();
    void First();          // 将迭代器指向第一个元素
    void Next();           // 将迭代器指向下一个元素
    bool IsDone();         // 判断是否遍历结束
    Object CurrentItem();  // 获取当前元素
protected:
private:
    Aggregate* _ag;  // 聚合对象
    int _idx;        // 当前索引
};

#endif //~_ITERATOR_H_

代码片段 4:Iterator.cpp

cpp 复制代码
// Iterator.cpp
#include "Iterator.h"
#include "Aggregate.h"
#include <iostream>
using namespace std;

// Iterator 类的实现
Iterator::Iterator() {
    // 构造函数
}

Iterator::~Iterator() {
    // 析构函数
}

// ConcreteIterator 类的实现
ConcreteIterator::ConcreteIterator(Aggregate* ag, int idx) {
    this->_ag = ag;  // 初始化聚合对象
    this->_idx = idx;  // 初始化当前索引
}

ConcreteIterator::~ConcreteIterator() {
    // 析构函数
}

Object ConcreteIterator::CurrentItem() {
    // 获取当前元素
    return _ag->GetItem(_idx);
}

void ConcreteIterator::First() {
    // 将迭代器指向第一个元素
    _idx = 0;
}

void ConcreteIterator::Next() {
    // 将迭代器指向下一个元素
    if (_idx < _ag->GetSize()) {
        _idx++;
    }
}

bool ConcreteIterator::IsDone() {
    // 判断是否遍历结束
    return (_idx == _ag->GetSize());
}

代码片段 5:main.cpp

cpp 复制代码
// main.cpp
#include "Iterator.h"
#include "Aggregate.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
    // 创建聚合对象
    Aggregate* ag = new ConcreteAggregate();

    // 创建迭代器对象
    Iterator* it = ag->CreateIterator();

    // 遍历聚合对象
    for (; !(it->IsDone()); it->Next()) {
        cout << it->CurrentItem() << endl;
    }

    // 释放内存
    delete it;
    delete ag;

    return 0;
}

代码说明

(1)Aggregate 类:定义了创建 Iterator 对象的接口,并提供了获取聚合对象大小和元素的方法。

(2)ConcreteAggregate 类:实现了 Aggregate 接口,内部维护了一个固定大小的数组。

(3)Iterator 类:定义了遍历聚合对象的接口,包括移动到第一个元素、移动到下一个元素、判断是否遍历结束以及获取当前元素的方法。

(4)ConcreteIterator 类:实现了 Iterator 接口,负责遍历 ConcreteAggregate 对象。

四、总结讨论

Iterator 模式的应用非常广泛,尤其是在需要对聚合对象进行遍历时。通过将遍历逻辑封装到独立的 Iterator 类中,我们可以实现以下优点:

(1)简化遍历操作:客户端代码只需要调用 Iterator 的接口即可完成遍历,无需关心聚合对象的内部实现。

(2)提高代码复用性:可以为不同的聚合对象提供统一的遍历接口。

(3)增强灵活性:可以在不修改聚合对象的情况下,扩展或修改遍历逻辑。

在实际开发中,STL 提供的 Iterator 就是一个典型的应用。例如,我们可以使用 `std::vector<int>::iterator` 来遍历 `std::vector<int>`,而无需关心 `std::vector` 的内部实现。

Iterator 模式通过将对聚合对象的遍历操作封装到独立的类中,实现了遍历逻辑与聚合对象的解耦。这种设计模式不仅简化了代码结构,还提高了代码的可维护性和可扩展性。在实际开发中,Iterator 模式是处理聚合对象遍历问题的首选方案。

相关推荐
用户6242931966213 小时前
告别 Electron 臃肿与 Wireshark 老化界面:用 Rust + Tauri 2.0 构建多总线网络与现场总线深度分析仪 Omni-Probe
设计模式
是2的10次方啊15 小时前
设计模式与生活㉒:暖气热不热,得一间一间摸过去
设计模式
ShineWinsu15 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽15 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
bigbread20 小时前
迭代器模式-在区域健康档案导出中的实战应用
设计模式
汉克老师21 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
装不满的克莱因瓶1 天前
设计模式之策略模式核心概念和应用场景
java·后端·设计模式·架构·系统架构·策略模式
晴天的雨.9921 天前
【C++】继承篇
java·开发语言·c++
青少儿编程课堂1 天前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
another heaven1 天前
【C/C++ 第一次跨越(上):用 C++11/14 停止制造新的旧代码】
c语言·c++·制造