一、概述
迭代器是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。
二、结构
- 迭代器(Iterator):接口类,声明了遍历集合所需的操作(获取下一个元素、获取当前位置和重新开始迭代等)。
- 具体迭代器(Concrete Iterators) :实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度,这使得多个迭代器可以相互独立地遍历同一集合。
- 集合(Collection):接口类,声明一个或多个方法来获取与集合兼容的迭代器。请注意,返回方法的类型必须被声明为迭代器接口,因此具体集合可以返回各种不同种类的迭代器。
- 具体集合(Concrete Collections) :会在客户端请求迭代器时返回一个特定的具体迭代器类实体。
- 客户端(Client):通过集合和迭代器的接口与两者进行交互。这样一来客户端无需与具体类进行耦合,允许同一客户端代码使用各种不同的集合和迭代器。客户端通常不会自行创建迭代器,而是会从集合中获取。但在特定情况下,客户端可以直接创建一个迭代器(例如当客户端需要自定义特殊迭代器时)。
三、适用场景
- 集合复杂的数据结构,希望对客户端隐藏其复杂性时(出于使用便利性或安全性的考虑),可以使用迭代器模式。
- 代码能够遍历不同的甚至是无法预知的数据结构,可以使用迭代器模式。
四、实例
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// 抽象迭代器,接口
class TVIterator {
public:
virtual void setChannel(int i) = 0;
virtual void next() = 0;
virtual void previous() = 0;
virtual bool isLast() = 0;
virtual string currentChannel() = 0;
virtual bool isFirst() = 0;
};
//具体实现方法迭代器
class SkyworthIterator :public TVIterator {
private:
vector<string>& tvs_;
int current_index_ = 0;
public:
explicit SkyworthIterator(vector<string>& tvs) :tvs_(tvs) {}
void next() override {
if (current_index_ < tvs_.size())
{
current_index_++;
}
}
void previous()override {
if (current_index_ > 0) {
current_index_--;
}
}
void setChannel(int i)override {
current_index_ = i;
}
string currentChannel()override {
return tvs_[current_index_];
}
bool isLast()override {
return current_index_ == tvs_.size();
}
bool isFirst()override {
return current_index_ == 0;
}
};
//抽象集合
class Television {
public:
virtual shared_ptr<TVIterator>createIterator() = 0;
};
class SkyworthTelevision : public Television {
private:
vector<string>tvs_;
public:
shared_ptr<TVIterator> createIterator() {
return make_shared<SkyworthIterator>(tvs_);
}
void addItem(string item) {
tvs_.push_back(item);
}
};
int main()
{
SkyworthTelevision stv;
stv.addItem("CCTV-1");
stv.addItem("CCTV-2");
stv.addItem("CCTV-3");
stv.addItem("CCTV-4");
stv.addItem("CCTV-5");
auto iter = stv.createIterator();
while (!iter->isLast())
{
cout << iter->currentChannel() << endl;
iter->next();
}
return 0;
}
五、优缺点
优点:
- 单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,你可对客户端代码和集合进行整理。
- 开闭原则。你可实现新型的集合和迭代器并将其传递给现有代码,无需修改现有代码。
- 可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。
- 可以暂停遍历并在需要时继续。
缺点:
- 对于某些特殊集合,使用迭代器可能比直接遍历的效率低。
- 程序只与简单的集合进行交互,应用该模式可能会矫枉过正。