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;
    }
    @Override
    public boolean hasNext() {
        return index < elements.size();
    }
    @Override
    public 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;
    }
    @Override
    public 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);
    }
    // 迭代器接口函数重载  返回值为迭代器基类的指针 模板类型为Student
    Iterator<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.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯---三羊献瑞

观察下面的加法算式: 其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。 请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。 答案 代码 public class _03三羊献瑞 {public static void main(String[] args) {//c 生 b 瑞 g 献 d 辉…

算法练习-螺旋矩阵(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;数组 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。以下内容均为个人笔记&#xff0c;旨在督促自己认真学习。 题目 给定一个正整数n&#xff0c;生成一个包含1到 n^2 所有元…

BACnet网关BL121BN 实现稳定可靠、低成本、简单的楼宇自控协议BACnet转OPC UA解决方案

随着楼宇自控系统的迅猛发展&#xff0c;人们深刻认识到在楼宇暖通行业中&#xff0c;实时、可靠、安全的数据传输至关重要。在此背景下&#xff0c;高性能的楼宇暖通数据传输解决方案——协议转换网关应运而生&#xff0c;广泛应用于楼宇自控和暖通空调系统应用中。 钡铼技术…

【数据结构】 循环队列的基本操作 (C语言版)

目录 一、顺序队列 1、顺序队列的定义&#xff1a; 2、顺序队列的优缺点&#xff1a; 二、循环队列 1、循环队列的定义&#xff1a; 2、循环队列的优缺点&#xff1a; 三、循环队列的基本操作算法&#xff08;C语言&#xff09; 1、宏定义 2、创建结构体 3、循环队…

PPO学习

openai用tf实现的真的看不懂&#xff0c;大佬的世界… PPO的详细细节 1. 奖励模型和策略的价值头将 query 和 response 的连接作为输入 奖励模型和策略的价值头 不 仅仅查看响应。相反&#xff0c;它将 query 和 response 连接在一起&#xff0c;作为 query_response def ge…

如何群发邮件outlook?外贸邮件群发教程?

outlook怎么设置邮件群发&#xff1f;outlook邮箱群发邮件方法&#xff1f; 在日常生活中&#xff0c;我们经常需要给多个人发送相同的邮件。这时候&#xff0c;群发邮件就显得尤为重要。Outlook作为一款常用的办公软件&#xff0c;提供了强大的邮件群发功能。蜂邮EDM就教大家…

Linux 文件:IO接口详解及实操

一、C语言中的文件IO读写操作 在c语言文件中&#xff0c;创建、打开、读、写操作可以通过如下的代码进行&#xff1a; 1.1写文件 通过w指令对文件进行写入操作时&#xff0c;编译器会先将文件内容清空然后重新写入。 #include <stdio.h> #include <string.h> i…

前端上传大文件使用分片上传

前提:分片上传针对于一些大的文件、普通大小的文件使用element中的上传组件可以实现效果,例如几G的文件就会比较卡,所以这时候就需要用到分片上传~ 前端及后端分片上传笔记 效果:(上传进度展示) 效果:(上传成功的效果展示) 1、 新建一个上传组件 2、使用vue-simple-…

ATF(TF-A)安全通告TF-V11——恶意的SDEI SMC可能导致越界内存读取(CVE-2023-49100)

目录 一、ATF(TF-A)安全通告TFV-11 (CVE-2023-49100) 二、透过事务看本质SDEI是干啥的呢&#xff1f; 三、CVE-2023-49100 1、GICv2 systems 2、GICv3 systems 四、漏洞修复 一、ATF(TF-A)安全通告TFV-11 (CVE-2023-49100) Title 恶意的SDEI SMC可能导致越界内存读取&am…

java数据结构与算法刷题-----LeetCode667. 优美的排列 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 题目要求我们返回一个数组长度为n的数组&#xff0c;必须含有1~n…

ZK高可用架构涉及常用功能整理

ZK高可用架构涉及常用功能整理 1. zk的高可用系统架构和相关组件1.1 Quorum机制1.2 ZAB协议 2. zk的核心参数2.1 常规配置2.2 特殊优化配置 3. zk常用命令3.1 常用基础命令3.2 常用运维命令 4. 事务性4.1 数据写流程4.2 数据读流程 5. 疑问和思考5.1 zk不擅长处理哪些场景&…

详解一次一密

目录 一. 介绍 二. 一次一密方案 三. 正确性分析 四. 证明一次一密方案是完美安全 五. 一次一密的应用 六. 小结 一. 介绍 一次一密&#xff0c;英语写做one time pad。 在1917年&#xff0c;Vernam提出了一个完美安全的加密方案&#xff0c;后世将其称之为一次一密。在…

Element中的el-input-number+SpringBoot+mysql

1、编写模板 <el-form ref"form" label-width"100px"><el-form-item label"商品id&#xff1a;"><el-input v-model"id" disabled></el-input></el-form-item><el-form-item label"商品名称&a…

选择国产压测工具应注意什么?

随着互联网和信息技术的飞速发展&#xff0c;压力测试成为了确保软件系统稳定性和性能的不可或缺的环节。在压测工具的选择上&#xff0c;近年来国产压测工具逐渐崭露头角&#xff0c;但在使用时仍需谨慎。本文将探讨在选择国产压测工具时需要注意的关键因素。 功能完备性&…

离线编译 onnxruntime-with-tensortRT

记录为centos7的4090开发机离线编译onnxruntime的过程&#xff0c;因为在离线的环境&#xff0c;所以踩了很多坑。 https://onnxruntime.ai/docs/execution-providers/TensorRT-ExecutionProvider.html 这里根据官网的推荐安装1.15 版本的onnx 因为离线环境&#xff0c;所以很…

中国大模型迎来“95后” 百度奖学金发掘百位“未来AI技术领袖”

在人工智能掀起的科技革命和产业变革浪潮下&#xff0c;大模型成为最受关注的研究领域。1月22日&#xff0c;第十一届百度奖学金颁奖典礼在北京举行&#xff0c;来自全球顶尖高校及科研机构的10位“未来AI技术领袖”脱颖而出&#xff0c;他们平均年龄仅27岁&#xff0c;其中8人…

关于Redis的最常见的十道面试题-分布式锁和布隆过滤器

面试题一&#xff1a;有序集合在日常工作中的使用场景有哪些&#xff1f; 有序集合在工作中的应用场景有很多&#xff0c;例如“ 排行榜&#xff1a;可以将用户的得分作为有序集合的分支&#xff0c;用户的ID作为成员&#xff0c;通过有序集合的排名功能可以得到用户的排名信…

OpenCV第 2 课 OpenCV 环境搭建

文章目录 第 2 课 OpenCV 环境搭建1.安装 Numpy2.从 Ubuntu 存储库安装 OpenCV3.验证 OpenCV 安装 第 2 课 OpenCV 环境搭建 1.安装 Numpy 每一张图像都有很多个像素点&#xff0c;这也导致了程序中会涉及大量的数组处理。Numpy 是一个 Python 的拓展库&#xff0c;它对多维数…

MySQL怎么根据当前时间获取连续十二个月统计数据

需求 在某些业务场景中&#xff0c;需要后台获取连续十二个月的统计数据&#xff0c;如下图&#xff1a; 解决方式 1、创建一张临时表&#xff0c;在表中插入序号数据 该表的最大数量决定统计返回的最大条数 CREATE TABLE sys_redundancy (id bigint(22) NOT NULL AUTO_I…

YOLOv7调用摄像头检测报错解决

yolov7detect.py文件调用本地摄像头&#xff0c;把source参数设为0 parser.add_argument(--source, typestr, default0, helpsource) # file/folder, 0 for webcam 报错&#xff1a;cv2.error: OpenCV(3.4.2) 一堆地址:The function is not implemented. Rebuild the library…