设计模式C++实现18:迭代器模式(Iterator)

news2024/11/16 3:39:23

意图:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

上下文:集合对象内部结构常常变化各异。对于这些集合对象,能否在不暴露其内部结构的同时,让外部Client透明地访问其中包含的元素,同时让这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供可能? 

迭代器模式静态类图 

Iterator:定义访问和遍历元素的接口(.NET中定义了标准的IEnumrator接口)。ConcreteIterator:实现Iterator接口,同时在对Aggregate遍历时跟踪当前的位置。Aggregate:定义创建相应Iterator对象的接口(.NET中定义了标准的IEnumrable接口)。ConcreteAggregate:实现创建相应Iterator对象的接口,该操作返回一个适当的ConcreteIterator实例。

注意:.NET中的foreach关键字在编译时会自动创建迭代器对象,并使用该对象对集合进行遍历。.NET中的yield return关键字使得定义迭代器对象更加容易。  

迭代器模式(Iterator)结构图 

测试代码:

额外需要的知识:运算符[ ]的重载,vector的用法。

#include <iostream>
#include <list>
#include <array>
#include <vector>
using namespace std;

//Iterator迭代器抽象类
class Iterator
{
public:
    virtual void* First() = 0;
    virtual void* Next() = 0;
    virtual bool IsDone() = 0;
    virtual void* CurrentItem() = 0;
};

//Aggregate聚集抽象类
class Aggregate
{
public:
    virtual Iterator *CreateIterator() = 0;
};

//ConcreteAggregate具体聚集类 继承Aggregate
class ConcreteAggregate:public Aggregate
{
public:
    vector<void*> items;
    // Aggregate interface
public:
    Iterator *CreateIterator();
    int getCount() const;
    //既可以作为左值,也可以作为又值
    void** operator[](unsigned int index){
        if(items.size() <= index){
            items.resize(index+1);
        }
        return &items[index];
    }
};

class ConcreteIterator:public Iterator
{
public:
    ConcreteAggregate *ca;
    int current;
    ConcreteIterator(ConcreteAggregate *c):ca(c){
        this->current = 0;
    }
    virtual void* First();
    virtual void* Next();
    virtual bool IsDone();
    virtual void* CurrentItem();
};

Iterator *ConcreteAggregate::CreateIterator()
{
    return new ConcreteIterator(this);
}

int ConcreteAggregate::getCount() const
{
    return items.size();
}

void *ConcreteIterator::First()
{
    return *(*ca)[0];
}

void *ConcreteIterator::Next()
{
    if(current < ca->getCount()){
        current++;
    }
    if(current < ca->getCount()){
        return *(*ca)[current];
    }
    return nullptr;
}

bool ConcreteIterator::IsDone()
{
    return current >= ca->getCount()?true:false;
}

void *ConcreteIterator::CurrentItem()
{
    return *(*ca)[current];
}

class ConcreteIteratorDesc:public Iterator
{
public:
    ConcreteAggregate *ca;
    int current;
    ConcreteIteratorDesc(ConcreteAggregate *c):ca(c){
        this->current = c->getCount() - 1;
    }
    virtual void* First();
    virtual void* Next();
    virtual bool IsDone();
    virtual void* CurrentItem();
};
void *ConcreteIteratorDesc::First()
{
    if(ca->getCount() == 0){
        return nullptr;
    }
    return *(*ca)[ca->getCount() - 1];
}

void *ConcreteIteratorDesc::Next()
{
    if(current >= 0){
        current--;
    }
    if(current >= 0){
        return *(*ca)[current];
    }
    return nullptr;
}

bool ConcreteIteratorDesc::IsDone()
{
    return current < 0?true:false;
}
void *ConcreteIteratorDesc::CurrentItem()
{
    return *(*ca)[current];
}
int main()
{
    ConcreteAggregate ca;
    *(ca[0]) = (void*)5;
    *ca[1] = (void*)10;
    *ca[2] = (void*)15;
    *ca[3] = (void*)20;
//    cout << (int) *ca[0] << endl;
//    cout << (int) *ca[1] << endl;
//    cout << ca.getCount() << endl;

    Iterator *i = new ConcreteIterator(&ca);

    cout << "开始遍历" << endl;
    while(!i->IsDone()){
        cout << (int)i->CurrentItem() << endl;
        i->Next();
    }

    Iterator *i_desc = new ConcreteIteratorDesc(&ca);

    cout << "开始反向遍历" << endl;
    while(!i_desc->IsDone()){
        cout << (int)i_desc->CurrentItem() << endl;
        i_desc->Next();
    }
    cout << "--end--" << endl;
    return 0;
}


运行结果:

开始遍历
5
10
15
20
开始反向遍历
20
15
10
5
--end--

小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/350649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态规划(楼梯和股票问题)

❤ 作者主页&#xff1a;李奕赫揍小邰的博客 ❀ 个人介绍&#xff1a;大家好&#xff0c;我是李奕赫&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 记得点赞、收藏、评论⭐️⭐️⭐️ &#x1f4e3; 认真学习!!!&#x1f389;&#x1f389; 文章目录动态规划&…

抓包工具Charles(一)-下载安装与设置

无论是在测试、开发工作中&#xff0c;抓包都是很重要、很常用的技能。Charles作为一款抓包工具&#xff0c;能够满足大部分的工作需求。 文章目录一、下载地址二、安装三、安装根证书&#xff08;电脑&#xff09;四、设置五、抓包附录&#xff1a;[零基础入门接口功能测试教程…

<JVM上篇:内存与垃圾回收篇>10 - StringTable

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录10.1. String 的基本特性10.1.1. String 在 jdk9 中存储结构变更MotivationDescription10.1.2. String 的基本特性10.2. String 的内…

ARMv8 同步和信号量(Synchronization and semaphores)简介

目录 1&#xff0c;Load-Exclusive/Store-Exclusive 概述 2&#xff0c;独占式访问指令与非共享内存( Exclusive access instructions and Non-shareable memory locations) 3&#xff0c;独占式访问指令与共享内存( Exclusive access instructions and shareable memory lo…

文华财经期货波段趋势K线结构主图阶梯公式源码,极品多空红绿轨道指标公式

期货指标公式是通过数学逻辑角度计算而来&#xff0c;仅是期货分析环节中的一个辅助工具。期货市场具有不确定性和不可预测性的&#xff0c;请正常对待和使用指标公式! 第一步&#xff1a;判大势 所谓判大势&#xff0c;就是判断当前行情趋势&#xff0c;是入场前的必备步骤。…

中汽协确认参加2023EVH新能源动力总成年会

演讲主题&#xff1a;中国汽车工业经济运行情况 演讲大纲&#xff1a; 对中国汽车工业近期发展态势进行分析2023年汽车行业预测 陈士华 现任中国汽车工业协会副秘书长&#xff0c;兼任中国汽车工业经济技术信息研究所有限公司总经理 1999年3月至今&#xff0c;就职于中国汽…

接口自动化测试框架(Java 实现)

需求分析 需求点需求分析通过 yaml 配置接口操作和用例后续新增接口和测试用例只需要编写 yaml 文件即可实现。可以支持接口间的参数传递具有参数依赖的接口可以进行变量的抽取和参数赋值。支持全局、用例维度的变量存储比如时间截命名法中要用到的时间截后缀。支持用例软断言…

Go语言入门【10】Map

Map map是一种键值对形式的数据结构&#xff0c;一个键对应一个值&#xff0c;可以通过键快速检索出其对应的value值&#xff0c;在map中key的值是唯一的&#xff0c;value的值不唯一&#xff0c;并且map中保存的数据是无序的。 Map声明 声明Map可以使用map关键字进行声明&a…

【Yolov7】配置参数以及训练模型

一、下载Yolov7 github地址&#xff1a;https://github.com/WongKinYiu/yolov7 或者命令行下载 git clone https://github.com/WongKinYiu/yolov7.git二、新建一个Python环境 用Acaconda新建一个干净的环境&#xff0c;我命名为yolov7&#xff0c;python版本选择3.8 进入到…

GPT系列:GPT, GPT-2, GPT-3精简总结 (模型结构+训练范式+实验)

&#x1f604; 花一个小时快速跟着 人生导师-李沐 过了一遍GPT, GPT-2, GPT-3。下面精简地总结了GPT系列的模型结构训练范式实验。 文章目录1、GPT1.1、模型结构&#xff1a;1.2、范式&#xff1a;预训练 finetune1.3、实验部分:2、GPT-22.1、模型结构2.2、范式&#xff1a;预…

C语言运算符(左值右值,基本运算符)

一.数据对象&#xff0c;左值&#xff0c;右值&#xff0c;运算符 数据对象&#xff1a;用于存储值的数据存储区域统称&#xff0c;而使用变量名是标识对象的一种方法&#xff08;还有指针&#xff0c;后面会教的&#xff09; 左值&#xff1a;用于标识特定数据对象的名称或表…

图的总复习

一、图的定义Graph 图是由顶点vertex集合及顶点间关系集合组成的一种数据结构&#xff1a; 顶点的集合 和 边的集合 二、无向图 用&#xff08;x,y&#xff09;表示两个顶点x和y之间的一条边&#xff08;edge&#xff09; 边是无方向的 N{V&#xff0c;E}&#xff0c;V{0…

【学习总结】2023寒假总结

写在前面时光匆匆&#xff0c;白驹过隙&#xff0c;转眼间寒假就过去了&#xff0c;这次寒假可以算的上是最长的一次假期&#xff0c;经历了从疫情到放开&#xff0c;从患病到阳康&#xff0c;在现实与虚幻的世界中玩耍&#xff0c;在痛苦的数据结构中徘徊&#xff0c;在每次早…

FFMPEG自学一 音视频解封装

一、音视频包含哪些数据对于一个mp4文件我们可以通过音视频分析软件打开查看内部信息。从两图可以看出mp4文件一般包含 音频流 视频流等。对于上面的字段大致分析如下Format编码方式AVC现在大部分视频都是这种编码方式&#xff0c;即H264。CodecId编码器idavc1H264封装有2种格式…

(二)随处可见的LED广告屏是怎么工作的呢?代码实现

书接上回&#xff0c;上一篇中我们聊到了LED点阵屏的工作原理和一些电气参数。本篇以第一篇为基础&#xff0c;对软件层面进行展开&#xff0c;同时也为下一篇接入GUI做铺垫。文章较第一篇有所增长&#xff0c;大概需要5~7分钟可以看完。【目标】能够随心所欲的显示我们想要的图…

OpenWrt之IPv6设置详解

文章目录前言网络结构1. WAN口设置2. LAN口设置3. NAT6配置4. 接口状态5. 网站测试6. 关于端口放行后话前言 最近电信终于肯下发v6的地址了, 得为路由器配置一下了, 之前一直是处于关闭的状态, 今天重新设置回去. 从此有了v4与v6双公网地址. 网络结构 光猫设置为桥接路由器设…

金三银四必看的软件测试面试题宝典,背完offer随便拿

怎么来设计测试方案根据测试需求&#xff08;包括功能需求和非功能性需求&#xff09;&#xff0c;识别测试要点&#xff0c;识别测试环境要求&#xff0c;安排测试轮次&#xff0c;根据项目计划和开发计划做整体的测试安排。 被测试的特性&#xff1a;通过对需求规格说明书进行…

【软件测试】一位转型测试开发成功,工作两年测开岗的经验总结......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 小伍&#xff1a; 在…

win10电脑性能优化设置

win10电脑性能优化设置 目录win10电脑性能优化设置1.桌面图标显示2.wini2.1 “系统”2.1.1专注助手 关2.1.2 电源和睡眠 设置为从不2.1.3 存储 开2.2 网络和Internet2.3 个性化2.4 应用2.5 账户2.6 游戏2.7 隐私墨迹书写和键入个性化&#xff1a;关活动历史记录&#xff1a;全部…

怎么样用香港主机搭建游戏网站

香港是全球主要的互联网骨干节点&#xff0c;拥有质量较高的网络基础设施&#xff0c;在网络速度和稳定性方面表现良好。因此&#xff0c;使用香港主机搭建游戏网站可以使用户在游戏中的体验流畅且基本不会延迟情况。本文将向用户解释如何使用香港主机搭建游戏网站。在搭建游戏…