C++设计模式之迭代器模式

【声明】本题目来源于卡码网(https://kamacoder.com/)

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分


设计模式大纲】


【简介】

        --什么是迭代器模式(第19种设计模式)

        迭代器模式是⼀种行为设计模式,是⼀种使⽤频率⾮常⾼的设计模式,在各个语⾔中都有应用,其主要⽬的是提供⼀种统⼀的⽅式来访问⼀个聚合对象中的各个元素,而不需要暴露该对象的内部表示。通过迭代器,客户端可以顺序访问聚合对象的元素,而无需了解底层数据结构。

迭代器模式应⽤⼴泛,但是⼤多数语⾔都已经内置了迭代器接⼝,不需要⾃⼰实现。


【基本结构】

        迭代器模式包括以下⼏个重要角色

  • 迭代器接口Iterator :定义访问和遍历元素的接⼝, 通常会包括hasNext() ⽅法⽤于检查是否还有下⼀个元素,以及next() ⽅法⽤于获取下⼀个元素。有的还会实现获取第⼀个元素以及获取当前元素的⽅法。
  • 具体迭代器ConcreateIterator :实现迭代器接⼝,实现遍历逻辑对聚合对象进⾏遍历。
  • 抽象聚合类:定义了创建迭代器的接⼝,包括⼀个createIterator ⽅法⽤于创建⼀个迭代器对象。
  • 具体聚合类:实现在抽象聚合类中声明的createIterator() ⽅法,返回⼀个与具体聚合对应的具体迭代器


【简易实现--Java】

        下面以Java代码作以说明:

1. 定义迭代器接口:通常会有检查是否还有下⼀个元素以及获取下⼀个元素的⽅法。

// 迭代器接⼝
public interface Iterator{// 检查是否还会有下⼀个元素boolean hasNext();// 获取下⼀个元素Object next();
}

2. 定义具体迭代器:实现迭代器接口,遍历集合。

public class ConcreteIterator implements Iterator {private int index;private List<Object> elements;// 构造函数初始化迭代器public ConcreteIterator(List<Object> elements) {this.elements = elements;this.index = 0;}@Overridepublic boolean hasNext() {return index < elements.size();}@Overridepublic Object next() {if (hasNext()) {return elements.get(index++);}return null;}
}

3. 定义聚合接口:通常包括createIterator() ⽅法,⽤于创建迭代器

public interface Iterable {Iterator createIterator();
}

4. 实现具体聚合:创建具体的迭代器

// 具体聚合
public class ConcreteIterable implements Iterable {private List<Object> elements;// 构造函数初始化可迭代对象public ConcreteIterable(List<Object> elements) {this.elements = elements;}@Overridepublic Iterator createIterator() {return new ConcreteIterator(elements);}
}

5. 客户端使用

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/23
*/
import java.util.ArrayList;
import java.util.List;
public class IteratorPatternExample {public static void main(String[] args) {List<Object> elements = new ArrayList<>();elements.add("Element 1");elements.add("Element 2");elements.add("Element 3");Iterable iterable = new ConcreteIterable(elements);Iterator iterator = iterable.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

【使用场景】

        迭代器模式是⼀种通用的设计模式,其封装性强,简化了客户端代码,客户端不需要知道集合的内部结构,只需要关心迭代器和迭代接口就可以完成元素的访问。但是引⼊迭代器模式会增加额外的类,每增加⼀个集合类,都需要增加该集合对应的迭代器,这也会使得代码结构变得更加复杂。
        许多编程语⾔和框架都使用了这个模式提供⼀致的遍历和访问集合元素的机制。下⾯是几种常见语⾔迭代器模式的实现。

1. Java语言

        集合类(如ArrayList、LinkedList), 通过Iterator 接⼝,可以遍历集合中的元素。

List<String> list = new ArrayList<>();
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {System.out.println(iterator.next());
}

2. Python语言

        使用迭代器和⽣成器来实现迭代模式, iter() 和next() 函数可以⽤于创建和访问迭代器。

elements = ["Element 1", "Element 2", "Element 3"]
iterator = iter(elements)while True:try:element = next(iterator)print(element)except StopIteration:break

3. C++语言

        C++中的STL提供了迭代器的⽀持, begin() 和end() 函数可以⽤于获取容器的起始和结束迭代器。

#include <iostream>
#include <vector>
int main() {std::vector<std::string> elements = {"Element 1", "Element 2", "Element 3"};for (auto it = elements.begin(); it != elements.end(); ++it) {std::cout << *it << std::endl;}return 0;
}

4. JavaScript语言

        ES6中新增了迭代器协议,使得遍历和访问集合元素变得更加方便。

// 可迭代对象实现可迭代协议
class IterableObject {constructor() {this.elements = [];}addElement(element) {this.elements.push(element);}[Symbol.iterator]() {let index = 0;// 迭代器对象实现迭代器协议return {next: () => {if (index < this.elements.length) {return { value: this.elements[index++], done: false };} else {return { done: true };}}};}
}
// 使⽤迭代器遍历可迭代对象
const iterableObject = new IterableObject();
iterableObject.addElement("Element 1");
iterableObject.addElement("Element 2");
iterableObject.addElement("Element 3");for (const element of iterableObject) {console.log(element);
}

【编码部分】

1. 题目描述

        小明是一位老师,在进行班级点名时,希望有一个学生名单系统,请你实现迭代器模式提供一个迭代器使得可以按顺序遍历学生列表。

2. 输入描述

        第一行是一个整数 N (1 <= N <= 100), 表示学生的数量。接下来的 N 行,每行包含一个学生的信息,格式为 姓名 学号;

3. 输出描述

        输出班级点名的结果,即按顺序遍历学生列表,输出学生的姓名和学号;

4. C++编程实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file IteratorMode.hpp
* @brief 迭代器模式
* @autor 写代码的小恐龙er
* @date 2024/01/23
*/#include <iostream>
#include <iomanip>
#include <string>
#include <vector>using namespace std;// 前置声明// 聚合元素类 -- 学生
class Student;// 迭代器接口 -- 提前声明模板
template<class T>
class Iterator;// 具体迭代器 -- 学生遍历 迭代类
class ConcreteStudentIterator;// 聚合接口 -- 学生全体类
class StudentCollection;// 具体的聚合类 -- 创建全体学生
class ConcreteStudentCollection;// 类的实现// 聚合元素类 -- 学生
class Student{
// 成员数据
private:string _name;int _idNumber;
// 成员函数
public:// 构造函数Student(string name, int id){this->_name = name;this->_idNumber = id;}// 获取成员数据string GetName(){return this->_name;}int GetIdNumber(){return this->_idNumber;}
};// 迭代器接口
// 类模板 
template<class T>
class Iterator{
// 迭代器接口
public:// 接口函数声明为 纯虚函数virtual bool isHavNext() = 0;virtual T* Next() = 0;
};// 具体迭代器 -- 学生遍历 迭代类
class ConcreteStudentIterator : public Iterator<Student>
{
// 成员数据 
private:std::vector<Student *> _studentsVec;int _currentIndex = 0;
// 成员函数
public:// 构造函数ConcreteStudentIterator(std::vector<Student *> studentsVec){this->_studentsVec = studentsVec;}// 重载接口函数bool isHavNext() override{return _currentIndex < _studentsVec.size();}Student*  Next() override {if(isHavNext()){return _studentsVec[_currentIndex++];}return nullptr;}
};// 聚合接口 -- 学生全体类
class StudentCollection
{
// 迭代器对象 接口函数
public:virtual Iterator<Student> * iterator() = 0;
};// 具体的聚合类 -- 创建全体学生
class ConcreteStudentCollection : public StudentCollection
{
// 成员数据 
private:std::vector<Student *> _students;
// 成员函数
public:// 构造函数ConcreteStudentCollection(){}ConcreteStudentCollection(std::vector<Student *> students){this->_students = students;}// 添加学生对象void AddStudent(Student * student){_students.push_back(student);}// 迭代器接口函数重载  返回值为迭代器基类的指针 模板类型为StudentIterator<Student> * iterator() override{// 涉及到 隐式地 向上类型转换 派生类 转换为 基类 线程安全return new ConcreteStudentIterator(_students);}
};int main()
{// 学生数量int studentNum = 0;// 输入std::cin >> studentNum;// 创建学生类Student *student = nullptr;// 创建具体可迭代对象ConcreteStudentCollection *concreteStudentCollection = new ConcreteStudentCollection();// 学生遍历for(int i = 0; i < studentNum; i++){// 学生姓名和学号string name = "";int numberId = 0;// 输入std::cin >> name >> numberId;// 构造学生类student = new Student(name, numberId);// 将学生放入 学生收集器类 中 concreteStudentCollection->AddStudent(student);}// 遍历结束后 再来通过迭代器模式 进行 信息打印// 调用具体聚合类中的 迭代器生成 接口!Iterator<Student> *iterator = concreteStudentCollection->iterator();while(iterator->isHavNext()){// 从迭代器中的学生集合获取学生类student = iterator->Next();// 打印学生信息if(student != nullptr){// 由于学生类中的成员数据为私有类型 记得调用接口函数去获取成员数据// 输出长度不足补0; 固定输出长度为3;std::cout << student->GetName() << " " << setw(3) << setfill('0') << student->GetIdNumber() << endl;}else std::cout << "Invalid input" << endl;}// 记得析构!!!// 记得析构!!!// 记得析构!!!if(student != nullptr){delete student;student = nullptr;}delete concreteStudentCollection;concreteStudentCollection = nullptr;return 0;
}


......

To be continued.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

消息中间件之Kafka(二)

1.Kafka线上常见问题 1.1 为什么要对topic下数据进行分区存储? 1.commit log文件会受到所在机器的文件系统大小的限制&#xff0c;分区之后可以将不同的分区放在不同的机器上&#xff0c; 相当于对数据做了分布式存储&#xff0c;理论上一个topic可以处理任意数量的数据2.提…

Hbas简介:数据模型和概念、物理视图

文章目录 说明零 BigTable一 Hbase简介二 HBase 访问接口简介三 行式&列式存储四 HBase 数据模型4.1 HBase 列族数据模型4.2 数据模型的相关概念4.3 数据坐标 五 概念&物理视图 说明 本文参考自林子雨老师的大数据技术原理与应用(第三版)教材内容&#xff0c;仅供学习…

MySQL---多表分组查询综合练习

创建dept表 CREATE TABLE dept ( deptno INT(2) NOT NULL COMMENT 部门编号, dname VARCHAR (15) COMMENT 部门名称, loc VARCHAR (20) COMMENT 地理位置 ); 添加dept表主键 mysql> alter table dept add primary key(deptno); Query OK, 0 rows affected (0.02 s…

Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

目录 AOP概念AOP底层原理AOP(JDK动态代理)使用 JDK 动态代理&#xff0c;使用 Proxy 类里面的方法创建代理对象**编写** **JDK** 动态代理代码 AOP(术语)AOP操作&#xff08;准备工作&#xff09;**AOP** **操作&#xff08;**AspectJ注解)**AOP** **操作&#xff08;**AspectJ…

GitHub无法完成推送 的设置选项

GitHub无法完成推送 的设置选项 系统设置 VS中控制台设置【指令】 控制台调出方法 以下为VS控制台指令 git config --global --unset http.proxy git config --global --unset https.proxygit config --global http.proxy 127.0.0.1:7890 git config --global https.proxy …

百万级监控指标的秒级采集与处理

随着云原生概念的深入普及和应用落地&#xff0c;企业应用架构由单体架构演进为微服务架构&#xff0c;应用将状态剥离到中间件层&#xff0c;通过无状态化实现更灵活的容器化部署和水平伸缩。然而&#xff0c;引入微服务框架、Kubernetes、分布式中间件等组件&#xff0c;使得…

定向减免!函数计算让 ETL 数据加工更简单

业内较为常见的高频短时 ETL 数据加工场景&#xff0c;即频率高时延短&#xff0c;一般费用大头均在函数调用次数上&#xff0c;推荐方案一般为攒批处理&#xff0c;高额的计算成本往往令用户感到头疼&#xff0c;函数计算推出定向减免方案&#xff0c;让 ETL数据加工更简单、更…

【漏洞复现】CloudPanel makefile接口远程命令执行漏洞(CVE-2023-35885)

文章目录 前言声明一、CloudPanel 简介二、漏洞描述三、影响版本四、漏洞复现五、修复建议 前言 CloudPanel 是一个基于 Web 的控制面板或管理界面&#xff0c;旨在简化云托管环境的管理。它提供了一个集中式平台&#xff0c;用于管理云基础架构的各个方面&#xff0c;包括 &a…

相关系数(皮尔逊相关系数和斯皮尔曼相关系数)

本文借鉴了数学建模清风老师的课件与思路&#xff0c;可以点击查看链接查看清风老师视频讲解&#xff1a;5.1 对数据进行描述性统计以及皮尔逊相关系数的计算方法_哔哩哔哩_bilibili 注&#xff1a;直接先看 &#xff08; 三、两个相关系数系数的比较 &#xff09; 部分&#x…

解决 BeanUtil.copyProperties 不同属性直接的复制

1、引入hutool <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version> </dependency> hutool官网 2、直接上例子 对象&#xff1a;User.java Data public class User {p…

二进制计算

二进制的引入 十进制规则:满10进1&#xff0c;由数字0到9组成。 而所谓十六进制&#xff0c;八进制&#xff0c;二进制的规则也是类似。 这里为了区分十六进制和八进制&#xff0c;十六进制前面会加上0x&#xff0c;八进制前面会加个0作为区分 而二进制的规则类似于十进制&…

ZEM20台式扫描电子显微镜在混凝土材料微观结构及性能研究中的应用

混凝土作为当今世界上使用量最大的建筑材料&#xff0c;广泛应用于桥梁、大坝、高楼等重要民用工程和设施中发挥着举足轻重的作用。但是普通混凝土存在抗压强度不高、脆性大等缺陷。此外&#xff0c;水泥生产过程还伴随着高能耗和二氧化碳排放问题。因此研发高性能、环保型混凝…

5G_射频测试_发射机测量(四)

6.2 Base station output power 用于测量载波发射功率的大小&#xff0c;功率越大小区半径越大但是杂散也会越大 载波功率&#xff08;用频谱仪测&#xff09;天线口功率&#xff08;用功率计测&#xff09;载波功率是以RBW为单位的filter测量的积分功率不同带宽的多载波测试时…

Jedis(一)与Redis的关系

一、Jedis介绍&#xff1a; 1、背景&#xff1a; Jedis是基于Java语言的Redis的客户端&#xff0c;Jedis Java Redis。Redis不仅可以使用命令来操作&#xff0c;现在基本上主流的语言都有API支持&#xff0c;比如Java、C#、C、PHP、Node.js、Go等。在官方网站里有一些Java的…

密码学的100个基本概念

密码学作为信息安全的基础&#xff0c;极为重要,本文分为上下两部分&#xff0c;总计10个章节&#xff0c;回顾了密码学的100个基本概念&#xff0c;供小伙伴们学习参考。本文将先介绍前五个章节的内容。 一、密码学历史 二、密码学基础 三、分组密码 四、序列密码 五、哈希…

【产品交互】超全面B端设计规范总结

不知不觉已经深耕在B端这个领域3年有余&#xff0c;很多人接触过B端后会觉得乏味&#xff0c;因为B端的设计在视觉上并没有C端那么有冲击力&#xff0c;更多的是结合业务逻辑&#xff0c;设计出符合业务需求的交互&#xff0c;以及界面排版的合理性&#xff0c;达到产品的可用性…

ARMv8-AArch64 的异常处理模型详解之异常类型 Exception types

异常类型详解 Exception types 一&#xff0c; 什么是异常二&#xff0c;同步异常&#xff08;synchronous exceptions&#xff09;2.1 无效的指令和陷阱异常&#xff08;Invalid instructions and trap exceptions&#xff09;2.2 内存访问产生的异常2.3 产生异常的指令2.4 调…

2024区块链应用趋势,RWA实物资产化

作者 张群&#xff08;赛联区块链教育首席讲师&#xff0c;工信部赛迪特聘资深专家&#xff0c;CSDN认证业界专家&#xff0c;微软认证专家&#xff0c;多家企业区块链产品顾问&#xff09;关注张群&#xff0c;为您提供一站式区块链技术和方案咨询。 实物资产通证化&#xff0…

PyTorch内置损失函数汇总 !!

文章目录 一、损失函数的概念 二、Pytorch内置损失函数 1. nn.CrossEntropyLoss 2. nn.NLLLoss 3. nn.NLLLoss2d 4. nn.BCELoss 5. nn.BCEWithLogitsLoss 6. nn.L1Loss 7. nn.MSELoss 8. nn.SmoothL1Loss 9. nn.PoissonNLLLoss 10. nn.KLDivLoss 11. nn.MarginRankingLoss 12. …

微信小程序(十二)在线图标与字体的获取与引入

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.从IconFont获取图标与文字的样式链接 2.将在线图标配置进页面中&#xff08;源码&#xff09; 3.将字体配置进页面文字中&#xff08;源码&#xff09; 4.css样式的多文件导入 获取链接 1.获取图标链接 登入…