1.简介
迭代器模式是一种行为设计模式, 让你能在不暴露集合(聚合对象)底层表现形式 (列表、 栈和树等) 的情况下遍历集合(聚合对象)中所有的元素。
迭代器的意义就是将这个行为抽离封装起来,这样客户端只需要调用合适的迭代器,来进行对应的遍历,而不用自己去实现这一行为。
2、结构
迭代器模式主要由以下几个结构组成:
迭代器(Iterator):定义访问和遍历聚合对象中元素的接口,包括获取下一个元素、判断是否还有下一个元素等方法。
具体迭代器(Concrete Iterator):实现迭代器接口,存储聚合对象的当前状态,负责遍历聚合对象中的元素。
聚合对象(Aggregate):定义创建相应迭代器对象的接口,一般是一个集合类,如列表、数组等。
具体聚合对象(Concrete Aggregate):实现聚合对象接口,创建具体迭代器对象,可以通过实现不同的聚合对象来提供不同方式的遍历。
在迭代器模式中,客户端通过获取聚合对象的迭代器,使用迭代器的方法遍历聚合对象中的元素,而无需暴露聚合对象的内部表示。这样可以提高系统的灵活性和可扩展性,同时也降低了聚合对象与迭代器之间的耦合度。
3、实现方式
3.1、案例引入
说到迭代器,大家应该很容易就想到在集合中的迭代器遍历集合的场景,这里我们就通过迭代器模式,自定义简单的集合和迭代器,模拟使用迭代器遍历集合的场景。
3.2、结构分析
在上述场景中,结构分别对应迭代器模式中的角色:
Container:对应迭代器模式中的抽象聚合类
ConcreteContainer:对应迭代器模式中的具体的聚合类
Iterator:对应迭代器模式中的抽象迭代器类;
ConcreteIterator:对应迭代器模式中的具体迭代器类;
3.3、具体实现
只在一个.cpp里实现,实际项目中建议分成多个文件
#pragma once#include <iostream>
#include <unordered_map>
#include <vector>
#include <list>
#include <string>using namespace std;//1. 定义迭代器接口
class Iterator
{
public:// 下一个virtual int getNext() = 0;// 是否有下一个virtual bool hasMore() = 0;};//2. 定义容器接口
class Container
{
public:virtual Iterator* create_iterator() = 0;
};//3. 定义具体迭代器
class ConcreteIterator : public Iterator
{
public:// 构造函数,初始化成员变量ConcreteIterator(std::vector<int> data) : m_data(data), index(0) {}// 下一个virtual int getNext() {return m_data[index++];}// 是否有下一个virtual bool hasMore() {return index < m_data.size();}private:std::vector<int> m_data;int index;};// 4.定义具体容器
class ConcreteContainer : public Container
{
public:// 构造函数ConcreteContainer(std::vector<int> data) : m_data(data) {}// 创建迭代器virtual Iterator* create_iterator() {return new ConcreteIterator(m_data);}private:std::vector<int> m_data;};int main()
{//1. 创建容器std::vector<int> data = { 10, 20, 30, 40, 50 };Container* container = new ConcreteContainer(data);//2.创建迭代器Iterator* iterator = container->create_iterator();//3. 迭代器输出while (iterator->hasMore()) {std::cout << iterator->getNext() << " ";}// 清除delete iterator;delete container;iterator = nullptr;container = nullptr;return 0;
}
3.4 运行结果
4.迭代器模式的优缺点
优点:
- 符合单一职责原则。将遍历行为抽离成单独的类。
- 符合开闭原则。添加新集合或者新迭代器,不改变原有代码
- 代码复用性好。由于迭代器模式将遍历集合的代码封装到迭代器中,因此我们可以将同样的迭代器应用于不同的集合对象,从而减少了重复的代码;
- 可以并行遍历同一集合。 因为每个迭代器对象都包含其自身的遍历状态。
缺点:
- 若对聚合对象只需要进行简单的遍历行为,那使用迭代器模式有些大材小用。
- 系统复杂性提高,类数量较多。
5、应用场景
- 在遍历集合元素时,不希望暴露集合内部的表示方式和数据结构,而是希望通过统一的接口进行操作。 迭代器模式使得我们可以将遍历行为封装在迭代器对象中,并把迭代器对象作为集合类的成员,从而达到这个目的;
- 当需要支持多种遍历方式时,可以使用迭代器模式。例如,在一个列表中,需要实现从前向后和从后向前两种遍历方式,使用迭代器模式非常方便地实现这样的需求;
- 需要提供一种通用的遍历机制,使得不同类型的集合对象都可以被遍历。由于迭代器模式将遍历过程封装在迭代器中,因此我们可以为每一种集合对象都提供一个对应的迭代器;
- 当需要对集合对象进行复杂的遍历操作时,可以使用迭代器模式。例如,有些集合对象可能需要在遍历过程中进行筛选、排序等处理,这些逻辑可以在迭代器中完成,从而使得客户端代码保持简洁。