定义:
它提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
说明:
目前基本上没人会单独写一个迭代器,除非是产品性质的开发
迭代器是为容器服务的,能容纳对象的所有类型的都可以称之为容器,迭代器模式就是胃解决遍历这些容器中的元素而诞生的。
迭代器模式提供了遍历容器的方便性,容器只要管理增减元素就可以了,需要遍历时交由迭代器进行。
示例一:迭代器模式(通用版)
1. 类图20-3
2. 结构说明
- Iterator 抽象迭代器:抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定的3个方法:first() 获得第一个元素, next() 访问下一个元素, isDone() 是否已经访问到底部
- ConcreteIterator 具体迭代器:具体迭代器角色要实现迭代器接口,完成容器元素的遍历。
- Aggregate 抽象容器:容器角色负责提供创建具体迭代器角色的接口,必然提供一个类似 createIterator() 这样的方法。
- Concrete Aggregate 具体容器:具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。
3. 代码清单
********** 3.迭代器模式(通用版),代码清单20-3:***************//
//抽象迭代器
class Interator
{
public:
virtual QString next() = 0;
virtual bool hasNext() = 0;
virtual bool remove() = 0;
};
//具体迭代器
class ConcreteIterator:public Interator
{
public:
ConcreteIterator()
:m_list()
,m_cursor(0)
{}
ConcreteIterator(QList<QString> list)
:m_list(list)
,m_cursor(0)
{}
virtual bool hasNext()
{
bool result = false;
if (this->m_cursor != this->m_list.size())
{
result = true;
}
return result;
}
virtual QString next()
{
QString object;
if (this->hasNext())
{
object = this->m_list.at(m_cursor++);
}
return object;
}
virtual bool remove()
{
this->m_list.removeAt(m_cursor++);
return true;
}
private:
QList<QString> m_list;
int m_cursor;
};
//抽象容器
class Aggregate
{
public:
virtual void add(QString object) = 0;
virtual void remove(QString object) = 0;
virtual Interator* iterator() = 0;
};
//具体容器
class ConcreteAggregate:public Aggregate
{
public:
ConcreteAggregate(){}
virtual void add(QString object)
{
this->m_list.push_back(object);
}
virtual void remove(QString object)
{
this->m_list.removeOne(object);
}
virtual Interator* iterator()
{
Interator* interactor = new ConcreteIterator(this->m_list);
return interactor;
}
private:
QList<QString> m_list;
};
int main()
{
Aggregate *agg = new ConcreteAggregate();
agg->add("abc");
agg->add("aaa");
agg->add("123");
Interator *iter = agg->iterator();
while(iter->hasNext())
{
qDebug() << iter->next();
}
return 0;
}
示例二:整理项目信息
1. 类图20-1
2..代码清单
// ********** 1.整理项目信息,代码清单20-1:***************//
//项目信息接口
class IProject
{
public:
virtual QString getProjectInfo() = 0;
};
//项目信息实现
class Project:public IProject
{
public:
Project(QString name, int num, int cost)
{
this->m_cost = cost;
this->m_name = name;
this->m_num = num;
}
virtual QString getProjectInfo() //这里用QString::number做了转化,否则在字符串拼接的时候输出会有错误
{
QString info;
info = "project name: " + m_name
+ " people num: " + QString::number(m_num)
+ " project cost: " + QString::number(m_cost);
return info;
}
private:
QString m_name; //项目名称
int m_num; //项目成员数量
int m_cost; //项目费用
};
int main ()
{
QList<IProject*> projectList;
IProject* pro1 = new Project("aaa", 10, 10000);
IProject* pro2 = new Project("bbb", 20, 20000);
IProject* pro3 = new Project("ccc", 30, 30000);
projectList.push_back(pro1);
projectList.push_back(pro2);
projectList.push_back(pro3);
QList<IProject*>::ConstIterator iter = projectList.begin();
while(iter != projectList.end())
{
IProject* project = *iter;
qDebug() << project->getProjectInfo();
++iter;
}
return 0;
}
示例三:整理项目信息(增加迭代器访问方式)
1. 类图20-2
2. 代码清单20-2
********** 2.整理项目信息(增加迭代器访问方式),代码清单20-2:***************//
class ProjectIterator;
//项目信息接口
class IProject
{
public:
virtual void add(QString name, int num, int cost) = 0;
virtual QString getProjectInfo() = 0;
virtual ProjectIterator* iterator() = 0;
};
typedef QList<IProject*> ProjectList;
//迭代器接口
class Interator
{
public:
virtual IProject* first() = 0;
virtual IProject* next() = 0;
virtual bool hasNext() = 0;
};
//迭代器实现
class ProjectIterator:public Interator
{
public:
ProjectIterator()
:m_list()
,m_current(0)
{}
ProjectIterator(ProjectList list)
:m_list()
,m_current(0)
{
this->m_list = list;
}
virtual IProject* first()
{
IProject* project = this->m_list.first();
return project;
}
virtual IProject* next()
{
IProject* project = nullptr;
if (this->hasNext())
{
project = this->m_list.at(m_current++);
}
return project;
}
virtual bool hasNext()
{
bool result = false;
if (this->m_current != this->m_list.size())
{
result = true;
}
return result;
}
private:
ProjectList m_list;
int m_current;
};
//项目信息实现
class Project:public IProject
{
public:
Project(){}
virtual void add(QString name, int num, int cost)
{
IProject *project = new Project(name, num, cost);
this->m_list.push_back(project);
}
virtual QString getProjectInfo() //这里用QString::number做了转化,否则在字符串拼接的时候输出会有错误
{
QString info;
info = "project name: " + m_name
+ " people num: " + QString::number(m_num)
+ " project cost: " + QString::number(m_cost);
return info;
}
virtual ProjectIterator* iterator()
{
ProjectIterator* proIter = new ProjectIterator(this->m_list);
return proIter;
}
private:
Project(QString name, int num, int cost)
{
this->m_cost = cost;
this->m_name = name;
this->m_num = num;
}
private:
QString m_name; //项目名称
int m_num; //项目成员数量
int m_cost; //项目费用
ProjectList m_list; //项目列表
};
int main ()
{
IProject* pro = new Project();
pro->add("aaa", 10, 10000);
pro->add("bbb", 20, 20000);
pro->add("ccc", 30, 30000);
ProjectIterator *proIter = pro->iterator();
while(proIter->hasNext())
{
qDebug() << proIter->next()->getProjectInfo();
}
return 0;
}
三、迭代器模式的应用
- 我们在例子中使用了迭代器模式后原本简单的应用编的复杂了,是因为我们在简单的应用中使用了迭代器。它为什么能够运行起来呢,是因为QList已经实现了iterator()方法,我们才可以简单地应用。
- 现在基本所有的高级语言都有迭代器的接口或实现,我们再去写迭代器,就有点多余了。所以迭代器模式有点没落了,基本上很少有项目再独立写迭代器了,直接使用已提供的就可以完美地解决问题了。
- 迭代器现在应用得越来越广泛了,甚至已经成为一个最基础的工具。
参考文献《秦小波. 设计模式之禅》(第2版) (华章原创精品) 机械工业出版社