17 行为型模式-----迭代器模式
模式动机(Iterator Pattern):对于聚合类的对象进行访问时,比如list,queue等,我们总希望有一个统一的访问接口,或者实现对多个聚合类对象的统一访问,或者实现对一个聚合类的多种不同访问方式,此时迭代器模式可以满足我们的这种需求。
迭代器就是在不暴露聚合类对象内部结构的前提下,对外提供了一种访问该对象的方法。
一般而言,一个迭代器是和一个聚合类紧密相连的。如何实现只允许迭代器访问聚合类的内部数据而避免其他类访问呢?这里需要借助于C++中的友元类,令迭代器类为聚合类 的友元类即可实现这个目标。
具体迭代器实现时有如下问题需要考虑:
1》 迭代遍历过程由迭代器控制还是由用户控制
若由用户控制时,这种迭代器称为外部迭代器。此时,客户必须负责向前推进遍历过程,显式地向迭代器请求下一个元素;若由迭代器控制,则称为内部迭代器。此时,迭代器会自动对聚合对象中的每个元素执行客户指定的操作。
大多数情况下,外部迭代器比内部迭代器更加灵活,可适应多个不同类型的聚合类对象,且扩展更容易。
2》 遍历算法是由迭代器定义还是由聚合类本身定义
若迭代器负责遍历算法,那么很容易在相同的聚合类上使用不同的迭代算法,同时也易于在不同的聚合类上使用同一迭代算法;若聚合类本身定义迭代算法,那么迭代器只负责存储遍历的当前状态,相当于一个指向当前状态的指针,因此我们称这种迭代器为游标(cursor)。
为了扩展迭代器的通用性,我们经常使用多态迭代器类型,即同时拥有一个抽象迭代器接口和具体迭代器实现类。对于不同类型的聚合对象,可以使用不同类型的迭代器实现类,这样就需要用工厂模式来分配迭代器对象。此时又有一个问题,分配的迭代器是谁来负责删除。如果由用户负责,可能造成内存泄漏,因为程序可能很复杂而忘记delete,或者在delete之前程序发生了异常。那么如何解决呢?
方法就是使用代理模式在栈上分配一个迭代器代理,由该代理负责删除堆上分配的空间。这样当程序结束时,所有分配的空间都会得到释放。要定义这种迭代器代理,必须实现如下操作:
1> 支持解引用操作 *
2> 赋值操作 =
3> ->操作
4> 比较操作,如!= / ==
5> 自增操作 ++
为了代码的简洁性,我们只重载了 -> 操作,另外需要将复制构造函数和赋值操作运算符声明为private,这样既可以防止多次delete同一对象,又可以防止编译器提供的默认实现。
模式结构图:
模式代码:
bt_迭代模式.h:
1 #ifndef IP_H 2 #define IP_H 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 /* 8 抽象迭代器 9 */ 10 class Iterator 11 { 12 public: 13 virtual ~Iterator(){ } 14 virtual void First() = 0; 15 virtual void Next() = 0; 16 virtual bool IsDone() = 0; 17 virtual char CurrentItem() = 0; 18 }; 19 20 /* 21 抽象聚合类 22 */ 23 class Aggregate 24 { 25 public: 26 virtual ~Aggregate(){ } 27 virtual Iterator* CreateIterator() = 0; 28 virtual int Count() const = 0; 29 virtual char Get(int index) const = 0; 30 }; 31 32 33 /* 34 具体迭代器 35 */ 36 class ConcreteIterator : public Iterator 37 { 38 public: 39 ConcreteIterator(const Aggregate* a) : aggregate(a), currentIndex(0){ } 40 virtual void First(){ currentIndex = 0; } 41 virtual void Next(){ currentIndex++; } 42 virtual bool IsDone(){ return currentIndex >= aggregate->Count(); } 43 virtual char CurrentItem() 44 { 45 if(IsDone()) 46 { 47 cout << "已遍历完毕" << endl; 48 return 0; 49 } 50 else 51 return aggregate->Get(currentIndex); 52 } 53 54 private: 55 const Aggregate* aggregate; 56 int currentIndex; 57 }; 58 59 /* 60 具体聚合类 61 */ 62 class ConcreteAggregate : public Aggregate 63 { 64 public: 65 ConcreteAggregate(string str){ name = str; } 66 virtual Iterator* CreateIterator() 67 { 68 return new ConcreteIterator(this); 69 } 70 virtual int Count() const{ return name.size(); } 71 virtual char Get(int index) const{ return name.at(index); }; 72 73 private: 74 string name; 75 }; 76 77 #endif // IP_H
测试用例.cpp:
1 #include "bt_迭代器模式.h" 2 int main() 3 { 4 cout << "***** 迭代器模式测试 *****" << endl; 5 string name("benxintuzi"); 6 Aggregate* aggregate = new ConcreteAggregate(name); 7 Iterator* iter = new ConcreteIterator(aggregate); 8 for(iter->First(); !iter->IsDone(); iter->Next()) 9 cout << iter->CurrentItem() << endl; 10 11 delete iter; 12 delete aggregate; 13 14 return 0; 15 }
模式扩展:
将迭代器模式进行扩展,使得可以通过迭代器代理自己释放分配的内存,而不是依赖客户的手动操作。定义代理类如下:
// ...class IteratorPtr /* 迭代器的代理类 */ { public:IteratorPtr(Iterator* it) : iter(it){ }~IteratorPtr(){ delete iter; } // 删除堆上的迭代器Iterator* operator->(){ return iter; }private:IteratorPtr(const IteratorPtr&);IteratorPtr& operator=(const IteratorPtr&);private:Iterator* iter; };// ...int main() {cout << "***** 迭代器代理模式测试 *****" << endl;string name("benxintuzi");Aggregate* aggregate = new ConcreteAggregate(name);IteratorPtr iterPtr(aggregate->CreateIterator()); // 对迭代器进行包装,并且代理类指定在栈上,程序结束后代理类对象自动回收for(iterPtr->First(); !iterPtr->IsDone(); iterPtr->Next())cout << (iterPtr->CurrentItem()) << endl;return 0; }
模式总结:
:: 支持以不同的方式遍历一个聚合类,只需定义抽象迭代器的具体实现类即可更改遍历方法。
:: 迭代器模式简化了聚合类的接口,使得聚合类本身不必再维护如何遍历的代价了。
:: 在同一个聚合类上,通过不同的迭代器实例可以同时执行多个遍历操作,互不影响。
转载于:https://www.cnblogs.com/benxintuzi/p/4568865.html
17 行为型模式-----迭代器模式相关推荐
- Java设计模式之行为型:迭代器模式
一.什么是迭代器模式: 实际开发中,我们针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但我们不希望在集合容器的抽象接口层中充斥着各种不同的遍历操作,这时候我们就需要一种能完成下面功能的迭代器 ...
- 设计模式 — 行为型模式 — 迭代器模式
目录 文章目录 目录 迭代器模式 应用场景 代码示例 迭代器模式 迭代器模式,对外提供一个接口,实现顺序访问聚合数据,但是不显示该数据的内部机制. Python 本身就很好的支持了迭代器模式,寥寥几行 ...
- Java设计模式(访问者模式-迭代器模式-观察者模式-中介者模式)
Java设计模式Ⅶ 1.访问者模式 1.1 访问者模式概述 1.2 代码理解 2.迭代器模式 2.1 迭代器模式概述 2.2 代码理解 3.观察者模式 3.1 观察者模式概述 3.2 代码理解 4.中 ...
- 设计模式的艺术 行为型模式之迭代器模式
前言 现在的电视机都配置了一个遥控器,用户可以通过遥控器去选择上一个或者下一个台,我们只需要知道如何使用这个遥控器,而无须关注电视是怎么把电视频道放入其中的,在软件实际的开发中,也有这么一种类,它储存 ...
- 创建型设计模模式---原型模式
设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...
- 行为型设计模式---模板方法模式
设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...
- 创建型设计模模式---建造者模式
设计模式 序号 内容 链接地址 1 设计模式七大原则 https://blog.csdn.net/qq_39668819/article/details/115390615 2 创建型设计模式–工厂模 ...
- 【设计模式】迭代器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
文章目录 一.迭代器模式简介 二.迭代器模式适用场景 三.迭代器模式优缺点 四.迭代器模式和访问者模式 五.迭代器模式代码示例 1.迭代器接口 2.迭代器实现 3.集合元素实例类 4.集合管理接口 5 ...
- Java设计模式之行为型:解释器模式
一.什么是解释器模式: 解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例. 这里我们将语言理解成使用规定格式和语 ...
- Java设计模式之行为型:访问者模式
背景: 去医院看病时,医生会给你一个处方单要你去拿药,拿药我们可以分为两步走: (1)去柜台交钱,划价人员会根据处方单上的药进行划价,交钱. (2)去药房拿药,药房工作者同样根据处方单给你相对应的药. ...
最新文章
- Android 聊天软件客户端
- xp框架下载官方_斐讯路由器系列「K1-K2-K2P-K2T」-Breed刷入工具v1.1支持XP系统
- Android复习10【Service与Thread的区别、Service的生命周期、Service生命周期解析(相关方法详解、启动方式的不同、绑定)、音乐播放器+服务】
- boost::graph模块实现斐波那契堆的测试程序
- basler相机 ip linux,Linux环境中连接Basler相机(Pylon软件的安装),ROS环境中连接Basler相机...
- python 图表 web_Web | Django 与 Chart.js 联用做出精美的图表
- 领域模型(domain model)贫血模型(anaemic domain model)充血模型(rich domain model)
- excel android 公式,两个超实用的Excel万能公式,瞬间提升你10倍工作效率!
- 虚拟机+Ubuntu+filezilla连接
- struts2之自定义拦截器及拦截器生命周期分析
- country-converter官方文档----机翻人工确认
- 学习微积分60年有感(III)
- java实现坦克大战
- html5简单表格制作
- 电信系统服务器地址,电信高速dns服务器地址谁知道?
- 正向/逆向最大匹配法分词实现
- 远程工具之一---rsync用法介绍
- 2020 最美最有意思辞职信
- python hasattr() getattr() setattr()函数的使用
- android进制之间的转换器,一个Android平台的16进制转换器
热门文章
- 十进制转36进制(10进制转任意进制的方法)
- POJ2492A Bug's Life【并查集+根节点偏移】
- PostgreSQL学习手册(三) 表的继承和分区
- 免费的分区软件MiniTool Partition Wizard Free
- Linux上运行Python文件
- bootstrap引入文件方法
- 【bzoj5001】搞事情 暴力
- android中ScrollView和GridView/ListView共存时,ScrollView不在顶部的解决方法
- Activity中的setDefaultKeyMode() (转载)
- hadoop2.xHA机制的实现原理