设计模式---数据结构模式之迭代器模式(Iterate)
一:概念
迭代模式是行为模式之一,它把对容器中包含的内部对象的访问委让给外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式。
在应用Iterator模式之前,首先应该明白Iterator模式用来解决什么问题。或者说,如果不使用Iterator模式,会存在什么问题?
.由容器自己实现顺序遍历。直接在容器类里直接添加顺序遍历方法
.让调用者自己实现遍历。直接暴露数据细节给外部。
以上方法1与方法2都可以实现对遍历,这样有问题呢?
,容器类承担了太多功能:一方面需要提供添加删除等本身应有的功能;一方面还需要提供遍历访问功能。
,往往容器在实现遍历的过程中,需要保存遍历状态,当跟元素的添加删除等功能夹杂在一起,很容易引起混乱和程序运行错误等。
Iterator模式就是为了有效地处理按顺序进行遍历访问的一种设计模式,简单地说,Iterator模式提供一种有效的方法,可以屏蔽聚集对象集合的容器类的实现细节,而能对容器内包含的对象元素按顺序进行有效的遍历访问。
所以,Iterator模式的应用场景可以归纳为满足以下几个条件:
.访问容器中包含的内部对象;
.按顺序访问
二:动机
在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明的访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。
使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“因对变化中的集合对象”提供了一种优雅的方式。
三:模式定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露(隔离变化,稳定)该对象的内部表示。 ——《设计模式》GoF
这种方式在C++现在来说已经过时了,因为泛型编程和STL中实现了迭代器。
迭代器模式最核心缺点就是出现在面向对象上,虚函数调用是有性能成本的,需要绕一个虚函数的表指针,然后找到函数地址,才能去调用,要经过指针间接运算。当循环次数太高后,性能就会被削减。
泛型编程中优点:迭代器是使用模板来实现的,而模板(也是一种多态技术),但是他实现的多态是编译时多态,编译器会在编译时判断具体是调用哪段代码。
虚函数是运行时多态,运行时多态性能低于编译时多态,编译时多态不需要计算他的地址了,因此STL性能高于面向对象模式迭代器,功能也更多。
四:类图(结构)
五:代码讲解
(一)Iterator基类
template<typename T>
class Iterator
{
public:
virtual void first() = ;
virtual void next() = ;
virtual bool isDone() const = ;
virtual T& current() = ;
};
(二)基类Collection返回迭代器
template<typename T>
class MyCollection{ public: Iterator<T> GetIterator(){
//...
} };
(三)子类CollectionIterator实现迭代方法
template<typename T>
class CollectionIterator : public Iterator<T>{
MyCollection<T> mc;
public: CollectionIterator(const MyCollection<T> & c): mc(c){ } void first() override { }
void next() override { }
bool isDone() const override{ }
T& current() override{ }
};
(四)进行调用
void MyAlgorithm()
{
MyCollection<int> mc; Iterator<int> iter= mc.GetIterator(); for (iter.first(); !iter.isDone(); iter.next()){
cout << iter.current() << endl;
} }
六:要点总结
(一)Java,C#类库是按照上面实现,因为毕竟没有编译时多态,现在C++基本没有这种实现,随着技术的发展,有些设计模式会过时,但是思想不会过时。
(二)迭代抽象:访问一个聚合对象的内容而无需暴露他的内部表示
(三)迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
(四)迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。
七:案例实现
(一)实现迭代器基类
class Iterator
{
public:
virtual void first() = ;
virtual void next() = ;
virtual bool isDone() const= ;
virtual int& current() = ;
virtual ~Iterator(){}
};
(二)实现聚合基类
class Aggregate
{
public:
virtual Iterator* CreateIntertor() = ;
virtual int getSize() = ;
virtual int getItem(int index) = ;
virtual ~Aggregate(){}
};
(三)实现具体迭代器子类
class ConcreteIterator :public Iterator
{
private:
Aggregate* _ag;
int _idx;
public:
ConcreteIterator(Aggregate* ag)
{
_ag = ag;
_idx = ;
} virtual void first()
{
_idx = ;
} virtual void next()
{
if (_idx<_ag->getSize())
_idx++;
} virtual bool isDone() const
{
return _idx == _ag->getSize();
} virtual int current()
{
return _ag->getItem(_idx);
}
};
(四)实现聚合子类
class ConcreteAggregate :public Aggregate
{
private:
int *Object;
int size;
public:
ConcreteAggregate(int size)
{
Object = (int *)malloc(size*sizeof(int)); for (int i = ; i < size; i++)
Object[i] = i*i; this->size = size;
} virtual Iterator* CreateIntertor()
{
return new ConcreteIterator(this);
} virtual int getSize()
{
return this->size;
} virtual int getItem(int index)
{
return this->Object[index];
} ~ConcreteAggregate()
{
delete Object;
}
};
(五)结果测试
int main()
{
Aggregate* ag = new ConcreteAggregate();
Iterator* it = ag->CreateIntertor(); for (it; !it->isDone(); it->next())
cout << it->current() << endl; delete it;
delete ag; system("pause");
return ;
}
作为迭代器,最好设置为模板类吧
#include <iostream>
#include <string> using namespace std; template<typename T>
class Iterator
{
public:
virtual void first() = ;
virtual void next() = ;
virtual bool isDone() const= ;
virtual T& current() = ;
virtual ~Iterator(){}
}; template<typename T>
class Aggregate
{
public:
virtual Iterator<T>* CreateIntertor() = ;
virtual int getSize() = ;
virtual T& getItem(int index) = ;
virtual ~Aggregate(){}
}; template<typename T>
class ConcreteIterator :public Iterator<T>
{
private:
Aggregate<T>* _ag;
int _idx;
public:
ConcreteIterator(Aggregate<T>* ag)
{
_ag = ag;
_idx = ;
} virtual void first()
{
_idx = ;
} virtual void next()
{
if (_idx<_ag->getSize())
_idx++;
} virtual bool isDone() const
{
return _idx == _ag->getSize();
} virtual T& current()
{
return _ag->getItem(_idx);
}
}; template<typename T>
class ConcreteAggregate :public Aggregate<T>
{
private:
T *Object;
int size;
public:
ConcreteAggregate(int size)
{
Object = (T *)malloc(size*sizeof(T)); for (int i = ; i < size; i++)
Object[i] = +i; this->size = size;
} virtual Iterator<T>* CreateIntertor()
{
return new ConcreteIterator<T>(this);
} virtual int getSize()
{
return this->size;
} virtual T& getItem(int index)
{
return this->Object[index];
} ~ConcreteAggregate()
{
delete Object;
}
}; int main()
{
Aggregate<char>* ag = new ConcreteAggregate<char>();
Iterator<char>* it = ag->CreateIntertor(); for (it; !it->isDone(); it->next())
cout << it->current() << endl; delete it;
delete ag; system("pause");
return ;
}
使用模板函数实现(重点)
设计模式---数据结构模式之迭代器模式(Iterate)的更多相关文章
- Javascript设计模式之我见:迭代器模式
大家好!本文介绍迭代器模式及其在Javascript中的应用. 模式介绍 定义 提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示. 类图及说明 Iterator抽象迭代器 抽象迭代器负 ...
- Java进阶篇设计模式之九----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
- Java设计模式之九 ----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
- Python使用设计模式中的责任链模式与迭代器模式的示例
Python使用设计模式中的责任链模式与迭代器模式的示例 这篇文章主要介绍了Python使用设计模式中的责任链模式与迭代器模式的示例,责任链模式与迭代器模式都可以被看作为行为型的设计模式,需要的朋友可 ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
- 设计模式(十七)——迭代器模式(ArrayList 集合应用源码分析)
1 看一个具体的需求 编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系.如图: 2 传统的设计方案(类图) 3 传统的方式的问题分析 ...
- C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第三个模式,该模式是[迭代器模式],英文名称是:Iterator Pattern.还是老套路,先从名字上来看看."迭代器模 ...
- C#设计模式之十五迭代器模式(Iterator Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第三个模式,该模式是[迭代器模式],英文名称是:Iterator Pattern.还是老套路,先从名字上来看看.“迭代器模式”我第一次看到这个名称,我的理解 ...
- C#设计模式(15)——迭代器模式
1.迭代器模式介绍 迭代器模式主要用于遍历聚合对象,将聚合对象的遍历行为分离出来,抽象为一个迭代器来负责.迭代器模式用的十分普遍,C#/JAVA等高级语言都对迭代器进行了封装用于遍历数组,集合,列表等 ...
随机推荐
- Android Studio 显示 logcat
首先调出 logcat,在整个android studio的左下角(藏的好,尼玛.) 接着设置下面三个红框 1 选择你自己的模拟器. 2 选择Warm 3 选择not filter
- 进入Docker容器的4种方式
进入Docker容器的4种方式 在使用Docker创建了容器之后,大家比较关心的就是如何进入该容器了,其实进入Docker容器有好几多种方式,这里我们就讲一下常用的几种进入Docker容器的方法. 进 ...
- java JUC
https://www.cnblogs.com/q151860/p/8589683.html
- 使用IDEA部署项目到远程服务器
1.选择Tools -> Deployment -> Configuration... 2.配置连接信息,Linux服务器一般都选择SFTP 3.配置本地上传文件路径.远程上传文件路径 4 ...
- linux tar 解压命令
如果提示 common not find 先进行安装如下 wget http://www.rarsoft.com/rar/rarlinux-5.3.0.tar.gz tar -zxvf rarlinu ...
- MT【307】周期数列
(2017浙江省数学竞赛) 设数列$\{a_n\}$满足:$|a_{n+1}-2a_n|=2,|a_n|\le2,n\in N^+$证明:如果$a_1$为有理数,则从某项后$\{a_n\}$为周期数列 ...
- MT【263】待定系数
已知$a,b>0$且$ab(a+b)=4$,求$2a+b$的最小值_____ 解答:$\sqrt{3}(2a+b)\ge(\sqrt{3}+1)a+b+(\sqrt{3}-1)(a+b)\ge3 ...
- 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)
Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...
- BZOJ4695 最假女选手(势能线段树)
BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...
- Tomcat如何发布web项目
tomcat/webapps目录是用来存放Java项目的.每一个文件夹都是一个项目,默认这个目录下已经有了四个项目,都是tomcat自带的. 其中ROOT就是我们测试Tomcat时访问的Tomcat的 ...