C++设计模式——Iterator迭代器模式

news2024/9/21 1:39:46

一,迭代器模式的定义

迭代器模式是一种行为型设计模式,它使得遍历一个容器对象中的元素变得更加简单。

迭代器模式将遍历操作从容器对象(如集合、列表)中分离出来,它通过迭代器对象来遍历容器对象中的元素,使得遍历操作与容器对象解耦。

迭代器模式可以解决的需求场景是当容器对象内部的结构经常被改变时,需要对外部屏蔽其变化过程。

迭代器模式对外提供了一个统一的遍历接口,这个接口可以顺序访问容器对象中的每个元素。

迭代器模式提供了遍历容器对象的方法,同时也隐藏了容器对象的实现细节,对容器对象的修改不影响迭代操作的使用。

迭代器模式在现实生活中的抽象实例:

1.图书馆中的书籍:在一个图书馆中,书籍可以看作是一个集合,每本书可以使用迭代器来逐个遍历。

2.超市货架上的商品:在超市中,货架上的商品可以使用迭代器来逐个检查和选择。

3.音乐播放器中的歌曲列表:在音乐播放器中,歌曲列表可以使用迭代器来逐个播放歌曲。

4.咖啡馆中的菜单:在咖啡馆中,菜单可以使用迭代器来逐个展示每种饮品和食物的信息。

在编程开发场景,迭代器的设计与实现有两种方式:

1.内部迭代器:通常是容器本身,由迭代器自身控制遍历过程,自发进行容器对象的访问和遍历,例如std::vector<int>,std::map<char, int>等。

2.外部迭代器:通常是独立于容器的接口,由调用者控制遍历过程,需要显示地访问容器对象中的元素,例如std::forward_iterator_tag等。

代码样例:

Demo1:内部迭代器

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    return 0;
}

运行结果:

1 2 3 4 5

Demo2:外部迭代器

#include <iostream>
#include <list>
#include <algorithm>
#include <string>

class MyData {
public:
    MyData(int tmpValue) {
        value = tmpValue;
    }
    int value;
};

template<typename T, typename OutIt>
OutIt print_data(const std::list<T>& container, OutIt out) {
    for (const auto& data : container) {
        *out++ = " [";
        *out++ = std::to_string(data.value);
        *out++ = "]";
    }
    return out;
}

int main() {
    std::list<MyData> dataList = { 10, 20, 30, 40, 50 };
    std::ostream_iterator<std::string> outIter(std::cout, "");
    print_data(dataList, outIter);
    return 0;
}

运行结果:

[10] [20] [30] [40] [50]

二,迭代器模式的结构

迭代器模式主要包含以下组件:

1.迭代器(Iterator):

定义了迭代器的接口,包括获取下一个元素、判断是否还有下一个元素等方法。负责定义访问和遍历元素的接口。

2.具体迭代器(ConcreteIterator):

包含对迭代器接口的具体实现。

3.容器(Aggregate):

定义了容器对象的接口,包括获取迭代器、添加元素等方法。还提供了创建迭代器对象的接口。

4.具体容器(ConcreteAggregate):

包含对容器的具体实现。通常会在具体容器中返回一个具体迭代器对象。

组件之间的工作步骤如下:

1.客户端通过容器对象获取迭代器对象。

2.客户端使用迭代器对象进行遍历操作,获取容器中的元素。

3.迭代器对象根据容器的具体实现,在每次调用获取下一个元素的方法时返回容器中的下一个元素。

4.客户端使用迭代器对象的判断是否有下一个元素的方法,来判断是否继续遍历容器中的元素。

5.客户端根据具体的业务逻辑来处理遍历到的每个元素。

对应UML类图:

三,迭代器模式代码样例

#include <iostream>
#include <vector>

class Iterator {
public:
    virtual bool hasNext() const = 0;
    virtual int next() = 0;
};

class ConcreteIterator: public Iterator {
private:
    std::vector<int> Aggregate;
    int index = 0;
public:
    ConcreteIterator(const std::vector<int>& vec){
        Aggregate = vec;
    }
    bool hasNext() const override {
        return index < Aggregate.size();
    }
    int next() override {
        return Aggregate[index++];
    }
};

class Aggregate {
public:
    virtual Iterator* createIterator() const = 0;
};

class ConcreteAggregate : public Aggregate {
private:
    std::vector<int> elements;
public:
    ConcreteAggregate(const std::vector<int>& vec){
        elements = vec;
    }
    Iterator* createIterator() const override {
        return new ConcreteIterator(elements);
    }
};

void traverseElements(ConcreteAggregate Aggregate) {
    Iterator* iterator = Aggregate.createIterator();
    while (iterator->hasNext()) {
        int element = iterator->next();
        std::cout << element << " ";
    }
    std::cout << std::endl;
    delete iterator;
}

int main() {
    std::vector<int> elements = { 1, 2, 3, 4, 5 };
    ConcreteAggregate Aggregate(elements);
    traverseElements(Aggregate);
    return 0;
}

运行结果:

1 2 3 4 5

四,迭代器模式的应用场景

数据的分层访问:当数据源复杂且需要逐步解析时,迭代器使得上层代码可以按需获取数据,而不必关心底层实现的细节。

流式处理:在大数据处理场景,通常采用惰性加载或逐行读取的方式,只在需要时才请求下一个元素,类似于缓存机制。

算法封装:许多高级算法,如排序、搜索和图计算等,都可以用迭代器来驱动,这样既通用又灵活。

数据库查询:数据库API通常会提供游标,用户借助游标逐条获取查询结果,而无需了解具体的SQL执行细节。

文件系统开发:在读取大文件或目录树时,使用迭代器模式来依次访问每个文件或子目录,避免一次性加载所有内容导致内存溢出。

五,迭代器模式的优缺点

迭代器模式的优点:

简化了对容器对象的遍历操作,提供了一个统一的遍历接口。

将遍历操作与容器对象进行了解耦,使得容器对象可以独立变化。

处理大批量数据时,操作简单。

迭代器模式的缺点:

通常按顺序进行遍历,不支持直接索引访问,无法做到高效获取元素。

需要时刻维护自己的状态,如当前位置,不当使用可能导致错误。

每次遍历都需要创建一个新的迭代器对象,内存消耗大。

六,代码实战

基于迭代器模式封装的链表

#include <iostream>

template <typename T>
struct Node {
    T data;
    Node* next;
};

template <typename T>
class Iterator {
public:
    virtual T next() = 0;
    virtual bool hasNext() = 0;
};

template <typename T>
class LinkedListIterator : public Iterator<T> {
public:
    LinkedListIterator(Node<T>* start){
        current_ = start;
    }
    T next() override {
        T data = current_->data;
        current_ = current_->next;
        return data;
    }
    bool hasNext() override {
        return current_ != nullptr;
    }
private:
    Node<T>* current_;
};

int main() {
    Node<int>* head = nullptr;
    for (int i = 6; i >= 1; i--) {
        Node<int>* newNode = new Node<int>{ i, head };
        head = newNode;
    }

    Iterator<int>* iterator = new LinkedListIterator<int>(head);
    while (iterator->hasNext()) {
        std::cout << iterator->next() << " ";
    }

    while (head != nullptr) {
        Node<int>* temp = head;
        head = head->next;
        delete temp;
    }

    delete iterator;
    return 0;
}

运行结果:

1 2 3 4 5 6

七,参考阅读

https://softwarepatterns.com/cpp/iterator-software-pattern-cpp-example

https://www.geeksforgeeks.org/iterator-pattern/

http://qiusuoge.com/13723.html

https://www.geeksforgeeks.org/stdistream_iterator-stdostream_iterator-c-stl/

https://en.cppreference.com/w/cpp/iterator/next

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

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

相关文章

若依后端正常启动但是uniapp移动端提示后端接口异常

pc端能用模拟器也能正常连接接口&#xff0c;手机端真机调试连不上接口 解决&#xff1a; 1. 先看config.js的 填自己的ip地址 module.exports { // baseUrl: https://vue.ruoyi.vip/prod-api, baseUrl: "http://192.168.101.5:8080", } 2.网络环境问题&#…

mysql -小计

//表单某字段值为当前打开文档Id (function () { var rdoc getRelateDocument(); var warehouseName rdoc.getItemValueAsString(“warehouseName”); var name rdoc.getItemValueAsString(“name”); var color rdoc.getItemValueAsString(“color”); var batchNumber r…

2024年Web前端JavaScript面试题整理附答案

&#xff08;1&#xff09;两等号判等&#xff0c;会在比较时进行类型转换&#xff1b; &#xff08;2&#xff09;三等号判等(判断严格)&#xff0c;比较时不进行隐式类型转换&#xff0c;(类 型不同则会返回false)&#xff1b; &#xff08;3&#xff09;Object.is 在三等号…

基于风力发电系统的开关磁阻Simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于风力发电系统的开关磁阻Simulink建模与仿真&#xff0c;开关磁阻风力发电系统&#xff08;Switched Reluctance Wind Power Generation System&#xff09;利用开关磁阻电…

计算机的错误计算(八十九)

摘要 探讨反双曲余切函数 acoth(x) 在 附近的计算精度问题。 Acoth(x) 函数的定义为&#xff1a; 其中 x 的绝对值大于 1 . 例1. 计算 acoth(1.000000000002) . 不妨在 Excel 的单元格中计算&#xff0c;则有&#xff1a; 若在Python中用定义直接计算&#xff0c;则有几乎…

SpringCloud神领物流学习笔记:项目概述(一)

SpringCloud神领物流学习笔记&#xff1a;项目概述&#xff08;一&#xff09; 文章目录 SpringCloud神领物流学习笔记&#xff1a;项目概述&#xff08;一&#xff09;1、项目介绍2、基本业务流程3、系统架构4、技术架构 1、项目介绍 ​ 神领物流是一个基于微服务架构体系的【…

Visual Studio 在 .NET MAUI 安装期间无法安装 OpenJDK v8 - 访问被拒绝

优质博文&#xff1a;IT-BLOG-CN 问题 我一直在 Windows 计算机上设置 Visual Studio 以进行 .NET MAUI 开发&#xff0c;但在设置过程中一直遇到问题。具体问题涉及 OpenJDK v8 无法安装。这是我看到的情况&#xff1a; Couldnt install OpenJDKv8我尝试过几种方法来解决这…

金融工程--论文资料整理方法

背景 1、金融工程的主要参考文献来源&#xff0c;帮助了解最新的量化研究进展。 2、这个工作其实对于所有的工程领域都能够使用。 3、如何使用ai工具提升阅读效率&#xff1f; 期刊文献来源 文献来源 https://zhuanlan.zhihu.com/p/549070754 这个网站能够很好帮助找到相关…

Linux(Ubuntu和CentOS通用)系统下源码安装Nginx_ubuntu和centos软件通用吗

<1>进入/home/zhangbao/nginx_install目录&#xff1a;cd /home/zhangbao/nginx_install <2>解压openssl-fips-2.0.16.tar.gz文件&#xff1a;tar -zxvf openssl-fips-2.0.16.tar.gz <3>进入openssl-fips-2.0.16解压包中&#xff1a;cd openssl-fips-2.0.16 …

什么是Aware注入?

Spring容器可以在Bean初始化的时候&#xff0c;自动注入一些特定信息&#xff08;如beanfactory&#xff09;,使得bean可以轻松的访问其他Bean的实例&#xff0c;简化代码&#xff0c;避免了显式的注入。 Spring提供了很多Aware的接口,如下&#xff1a; 拿其中的BeanFactoryAwa…

SprinBoot+Vue健身俱乐部网站系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

编曲术语:各种段落的英文表示 Cubasis和Cubase联合编曲

在编曲中&#xff0c;常见的段落英文表示如下&#xff1a; 前奏&#xff08;Intro&#xff09;&#xff1a;通常是歌曲开头的部分&#xff0c;用于引入主题&#xff0c;营造氛围。 主歌&#xff08;Verse&#xff09;&#xff1a;歌曲的主要叙述部分&#xff0c;一般有多段&am…

Vue实现自定义进度条占比功能 Vue自定义进度条功能

在不使用echarts等第三方插件的情况下,使用Vue实现自定义的进度条占比功能,并且是多数据可选循环的 预览图效果 首先看一下获取的后端返回的数据结构,其中每一组加起来等于 22 ,也就是说如果你自己算的话也是同理,根据 占比的数值 除以 总和 =的百分比再去渲染对应占比…

828华为云征文 | 标题:使用华为云X实例部署图数据库Virtuoso并存储6500万条大数据的完整过程与性能测评

前言 在大数据时代&#xff0c;图数据库以其强大的关系处理能力在复杂网络、社交媒体分析、知识图谱等领域得到了广泛应用。而在云计算的蓬勃发展下&#xff0c;使用云服务器进行图数据库的部署与管理变得更加方便高效。本篇文章将详细介绍如何在华为云X实例上部署开源图数据…

C++(2)之Linux多线程服务端编程总结

C之Linux多线程服务端编程读书笔记 Author: Once Day Date: 2023年1月31日/2024年8月23日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: Linux实践…

MySQL-CRUD入门2

文章目录 数据的查询(补充)条件查询关于SQL语句的执行顺序分页查询(LIMIT) 数据的修改数据修改基础知识 数据的查询(补充) 这一节接着写, 包括数据的查询(补充), 数据的更新, 数据的删除 条件查询 其实就是根据给定的一些条件, 然后过滤掉不符合实际情况的记录, 把符合条件的…

Spring Cloud之二 微服务注册

1&#xff1a;Intellij 新建服务 user-service 2&#xff1a;pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"…

知识库管理系统在企业数字化转型中的作用

引言 在数字化转型的浪潮中&#xff0c;企业正以前所未有的速度重塑其业务模式、运营流程和组织架构&#xff0c;以适应快速变化的市场环境和客户需求。这一过程中&#xff0c;知识库管理系统作为信息整合与知识共享的核心平台&#xff0c;发挥着举足轻重的作用&#xff0c;不…

2024/9/9 408“回头看”:b树

B树是什么&#xff1f;有什么作用&#xff1f;B树的插入和删除具体细节是什么&#xff1f;除了B树还有一个是B&#xff0b;树、还是B-树&#xff0c;他们有什么区别&#xff0c;又有什么相同点&#xff1f; b树在王道考研查找这一章&#xff0c;所以他的主要作用就是查找。 在…

基于单片机一种风速测量仪的设计

文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图参考文献设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…