迭代器模式是一种行为设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
基本概念
迭代器模式主要包含以下角色:
-
Iterator(迭代器):定义访问和遍历元素的接口
-
ConcreteIterator(具体迭代器):实现迭代器接口,负责管理当前元素的位置
-
Aggregate(聚合):定义创建相应迭代器对象的接口
-
ConcreteAggregate(具体聚合):实现创建相应迭代器的接口,返回具体迭代器的实例
实现示例
下面是一个完整的C++实现示例:
#include <iostream>
#include <vector>
#include <memory>
// 前向声明
template <typename T>
class ConcreteAggregate;
// 抽象迭代器
template <typename T>
class Iterator {
public:
virtual ~Iterator() = default;
virtual void first() = 0;
virtual void next() = 0;
virtual bool isDone() const = 0;
virtual T currentItem() const = 0;
};
// 具体迭代器
template <typename T>
class ConcreteIterator : public Iterator<T> {
public:
ConcreteIterator(const ConcreteAggregate<T>* aggregate)
: aggregate_(aggregate), current_(0) {}
void first() override {
current_ = 0;
}
void next() override {
++current_;
}
bool isDone() const override {
return current_ >= aggregate_->size();
}
T currentItem() const override {
if (isDone()) {
throw std::out_of_range("Iterator out of bounds");
}
return aggregate_->get(current_);
}
private:
const ConcreteAggregate<T>* aggregate_;
size_t current_;
};
// 抽象聚合
template <typename T>
class Aggregate {
public:
virtual ~Aggregate() = default;
virtual std::unique_ptr<Iterator<T>> createIterator() = 0;
};
// 具体聚合
template <typename T>
class ConcreteAggregate : public Aggregate<T> {
public:
void add(const T& item) {
items_.push_back(item);
}
T get(size_t index) const {
return items_[index];
}
size_t size() const {
return items_.size();
}
std::unique_ptr<Iterator<T>> createIterator() override {
return std::make_unique<ConcreteIterator<T>>(this);
}
private:
std::vector<T> items_;
};
// 使用示例
int main() {
ConcreteAggregate<int> aggregate;
for (int i = 0; i < 10; ++i) {
aggregate.add(i * 2);
}
auto iterator = aggregate.createIterator();
for (iterator->first(); !iterator->isDone(); iterator->next()) {
std::cout << iterator->currentItem() << " ";
}
std::cout << std::endl;
return 0;
}
STL中的迭代器实现
C++标准模板库(STL)广泛使用了迭代器模式。STL中的容器类都提供了自己的迭代器:
#include <vector>
#include <iostream>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用迭代器遍历
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 范围for循环(底层也是使用迭代器)
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
迭代器模式的优点
-
简化了聚合对象的接口:迭代器提供了一个统一的接口来遍历聚合对象,无需暴露内部结构
-
支持多种遍历方式:可以为同一个聚合对象提供多种遍历方式
-
支持并行遍历:可以同时使用多个迭代器进行遍历
-
符合单一职责原则:将遍历逻辑从聚合对象中分离出来
-
符合开闭原则:可以引入新的迭代器而不必修改聚合对象
迭代器模式的缺点
-
增加了类的数量:每个聚合类都需要对应的迭代器类,增加了系统的复杂性
-
对于简单聚合可能过度设计:如果聚合对象非常简单,直接暴露内部结构可能更简单
应用场景
-
当需要为聚合对象提供多种遍历方式时
-
当需要为聚合对象提供一个统一的遍历接口时
-
当需要隐藏聚合对象的内部结构时
-
当需要支持对聚合对象的并行遍历时
通俗总结
迭代器模式就像是一个"集合导游":
-
核心思想:
-
把"怎么遍历"和"存储什么"分开
-
给各种不同的集合(数组、链表等)提供统一的遍历方式
-
-
生活比喻:
-
想象你去博物馆,不管展品怎么摆放(有的按年代、有的按主题),导游都能用同样的方式带你参观
-
导游就是迭代器,博物馆就是集合
-
-
C++中的体现:
-
STL中的
begin()
/end()
就是典型迭代器 -
for(auto x : collection)
这种语法糖底层就是迭代器
-
-
三大好处:
-
对使用者:用同样的方式遍历任何集合
-
对集合:内部结构随便改,不影响遍历代码
-
对系统:可以同时多个遍历互不干扰
-
-
适用场景:
-
当你需要:"不管里面怎么存,我就要一个个取出来用"的时候
-
当你写:"for循环遍历某个集合"的时候,其实已经在用这个思想了
-
一句话总结:迭代器模式让不同的集合都能用同样的方式被遍历,就像不同的博物馆都能用同样的导游讲解方式参观。