设计模式:迭代器模式(Iterator)

设计模式:迭代器模式(Iterator)

  • 设计模式:迭代器模式(Iterator)
    • 模式动机
    • 模式定义
    • 模式结构
    • 时序图
    • 模式实现
    • 在单线程环境下的测试
    • 在多线程环境下的测试
    • 模式分析
    • 优缺点
    • 适用场景
    • 应用场景
    • 参考

设计模式:迭代器模式(Iterator)

迭代器模式(Iterator)属于行为型模式(Behavioral Pattern)的一种。

行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。

行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。

通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。在系统运行时,对象并不是孤立的,它们可以通过相互通信与协作完成某些复杂功能,一个对象在运行时也将影响到其他对象的运行。

行为型模式分为类行为型模式和对象行为型模式两种:

  1. 类行为型模式:类的行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态等方式来分配父类与子类的职责。
  2. 对象行为型模式:对象的行为型模式则使用对象的聚合关联关系来分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。根据“合成复用原则”,系统中要尽量使用关联关系来取代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。

模式动机

我们使用的聚合对象各种各样,比如vector、list、tree、map等等,既然是聚合,那就有访问其个体的需要。而遍历访问这个行为可能有深度优先、广度优先、顺序遍历、逆序遍历等等,迭代器的意义就是将这个行为抽离封装起来,这样客户端只需要调用合适的迭代器,来进行对应的遍历,而不用自己去实现这一行为。

模式定义

迭代器模式(Iterator)属于行为型模式。

迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中各个元素,而不暴露该对象的内部表示。通过迭代器,客户端可以顺序访问聚合对象的元素,而无需了解底层数据结构。

模式结构

迭代器模式(Iterator)包含如下角色:

  • 抽象聚合(Aggregate):抽象容器,定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
  • 具体聚合(ConcreteAggregate):具体容器,实现内部不同结构,返回一个迭代器实例。
  • 抽象迭代器(Iterator): 定义访问和遍历聚合元素的接口。
  • 具体迭代器(ConcreteIterator): 实现抽象迭代器接口中的方法,完成对聚合对象的遍历,记录遍历的当前位置。

在这里插入图片描述

从上图中,我们可以看到具体容器和具体迭代器两者是相互调用的,也就是说容器调用了迭代器,然后通过迭代器调用了容器内部自身的方法来实现封装。

时序图

略。

模式实现

以 vector 为例,设计了模板类。示例代码如下:

抽象迭代器 Iterator.h:

#ifndef _ITERATOR_H_
#define _ITERATOR_H_template<typename T>
class Iterator
{
public:// 第一个元素virtual T first() = 0;// 下一个元素virtual T next() = 0;// 是否到达容器的终点virtual bool isDone() = 0;// 获取当前元素的指针virtual T* currentItem() = 0;
};#endif // !_ITERATOR_H_

具体迭代器 ConcreteIterator.h:

#ifndef _CONCRETE_ITERATOR_H_
#define _CONCRETE_ITERATOR_H_#include <vector>
#include "Iterator.h"template<typename T>
class ConcreteIterator : public Iterator<T>
{
private:std::vector<T> m_data;int index;public:// 构造函数ConcreteIterator(std::vector<T> data) : m_data(data), index(0) {}T first(){return *m_data.begin();}T next(){if (isDone())return (T)0;return m_data[index++];}bool isDone(){if (index < m_data.size())return false;return true;}T* currentItem(){if (index < m_data.size())return &m_data[index];elsereturn nullptr;}
};#endif // !_CONCRETE_ITERATOR_H_

抽象聚合 Aggregate.h:

#ifndef _AGGREGATE_H_
#define _AGGREGATE_H_#include "Iterator.h"
#include "Aggregate.h"template<typename T>
class Aggregate
{
public:// 创建迭代器virtual Iterator<T>* createIterator() = 0;
};#endif // !_AGGREGATE_H_

具体聚合 ConcreteAggregate.h:

#ifndef _CONCRETE_AGGREGATE_H_
#define _CONCRETE_AGGREGATE_H_#include "ConcreteIterator.h"
#include "Aggregate.h"template<typename T>
class ConcreteAggregate : public Aggregate<T>
{
private:std::vector<T> m_data;public:// 构造函数ConcreteAggregate(std::vector<T> data) : m_data(data) {}Iterator<T>* createIterator(){return new ConcreteIterator<T>(m_data);}
};#endif // !_CONCRETE_AGGREGATE_H_

在单线程环境下的测试

测试代码,也可以说是 client:

#include <iostream>
#include <vector>
#include <stdlib.h>#include "ConcreteIterator.h"
#include "ConcreteAggregate.h"using namespace std;int main()
{vector<int> data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };// 创建容器和迭代器ConcreteAggregate<int>* aggregate = new ConcreteAggregate<int>(data);Iterator<int>* iterator = aggregate->createIterator();// 迭代器输出while (!iterator->isDone())cout << iterator->next() << " ";cout << endl;// 清除delete iterator;delete aggregate;iterator = nullptr;aggregate = nullptr;system("pause");return 0;
}

运行结果:

在这里插入图片描述

在多线程环境下的测试

略。

模式分析

  • 迭代器模式提供了一种统一的方式来遍历集合对象中的元素。
  • 它将遍历操作封装到一个独立的迭代器对象中,使得我们可以按照特定的方式访问集合中的元素。
  • 迭代器模式将集合对象和遍历操作分离开来,提高了代码的灵活性和可维护性。
  • 使用迭代器模式可以让我们用相同的方式遍历不同类型的集合对象,而不需要了解集合的内部结构。

优缺点

优点:

  1. 符合单一职责原则。将遍历行为抽离成单独的类。
  2. 符合开闭原则。如果需要增加新的遍历方式,只需实现一个新的具体迭代器即可,不需要修改原先聚合对象的代码。
  3. 简化了集合类的接口,使用者可以更加简单地遍历集合对象,而不需要了解集合内部结构和实现细节。
  4. 将集合和遍历操作解耦,使得我们可以更灵活地使用不同的迭代器来遍历同一个集合,根据需求选择不同的遍历方式。

缺点:

  1. 不适合每种场景:若对聚合对象只需要进行简单的遍历行为,那使用迭代器模式有些大材小用。
  2. 遍历效率降低:在某些情况下,使用迭代器模式可能会导致遍历效率降低,特别是使用外部迭代器时,需要手动进行迭代操作。
  3. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

适用场景

  1. 访问一个聚合对象的内容而无须暴露它的内部表示。
  2. 需要为聚合对象提供多种遍历方式。
  3. 减少与集合对象的耦合。
  4. 为遍历不同的聚合结构提供一个统一的接口。
  5. 提供一个便利的方法访问一个聚合对象中的每个元素。

应用场景

  1. 集合框架中的迭代器:C++ 的 STL 容器一般都有自己的迭代器。在Java中,集合包括List、Set、Map等等,每个集合类中都提供了一个获取迭代器的方法,例如List提供的iterator()方法、Set提供的iterator()方法等等。通过获取对应的迭代器对象,可以对集合中的元素进行遍历和访问。
  2. JDBC中的ResultSet对象:在Java中,如果需要对数据库中的数据进行遍历和访问,可以使用JDBC操作数据库。JDBC中,查询结果集使用ResultSet对象来表示,通过使用ResultSet的next()方法,就可以像使用迭代器一样遍历和访问查询结果中的数据。
  3. 文件读取:在Java中,我们可以使用BufferedReader类来读取文本文件。BufferedReader类提供了一个方法readLine()来逐行读取文件内容。实际上,BufferedReader在内部使用了迭代器模式来逐行读取文本文件的内容。
  4. Python 使用迭代器和⽣成器来实现迭代模式,iter() 和next() 函数可以⽤于创建和访问迭代器。
  5. JavaScript:ES6中新增了迭代器协议,使得遍历和访问集合元素变得更加方便。

参考

  1. https://zhuanlan.zhihu.com/p/678005837
  2. https://blog.csdn.net/zhaitianbao/article/details/130097933
  3. https://hermit.blog.csdn.net/article/details/123429647
  4. https://www.cnblogs.com/ybqjymy/p/17534782.html
  5. https://blog.csdn.net/qq_42764269/article/details/127382043
  6. https://blog.csdn.net/K1_uestc/article/details/135772598
  7. https://blog.csdn.net/weixin_45433817/article/details/131382881
  8. https://www.runoob.com/design-pattern/iterator-pattern.html

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

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

相关文章

python爬虫(四)之九章智算汽车文章爬虫

python爬虫&#xff08;四&#xff09;之九章智算汽车文章爬虫 闲来没事就写一条爬虫抓取网页上的数据&#xff0c;现在数据已经抓完&#xff0c;将九章智算汽车文章的爬虫代码分享出来。当前代码采用python编写&#xff0c;可抓取所有文章&#xff0c;攻大家参考。 import r…

STL中的优先级队列

目录 1.引言 2.简介 3.基本操作 4.实现原理 5.自定义优先级比较 6.相关题目 7.能特点 8.总结 1.引言 在C标准库中&#xff0c;优先级队列是一种非常有用的数据结构&#xff0c;它允许我们根据元素的优先级来对其进行排序和访问。这种数据结构在多种应用场景中都发挥着重…

DockerFile介绍与使用

一、DockerFile介绍 大家好&#xff0c;今天给大家分享一下关于 DockerFile 的介绍与使用&#xff0c;DockerFile 是一个用于定义如何构建 Docker 镜像的文本文件&#xff0c;具体来说&#xff0c;具有以下重要作用&#xff1a; 标准化构建&#xff1a;提供了一种统一、可重复…

最大子矩阵:前缀和、动态规划

最近在学习动态规划&#xff0c;在牛客上刷题时碰到了这一题。其实最初的想法是暴力和前缀和&#xff0c;但是时间复杂度极高&#xff0c;需要套4层循环。后来去网上搜了一下相关的题解和做法&#xff0c;进而了解到了前缀和&#xff0b;线性动态规划的做法。但是在成功做出这题…

JVM 类的加载过程详解

文章目录 1. 哪些类需要加载2. 类加载步骤2.1 装载2.1.1 这个过程都做了什么事2.1.2 类的模板对象2.1.3 二进制流获取方式2.1.4 Class 实例的位置2.1.5 数组类的加载有什么不同 2.2 链接2.2.1 验证2.2.2 准备2.2.3 解析 2.3 初始化 1. 哪些类需要加载 在 Java 中数据类型分为 …

最好的网校在线教育系统,怎样才能有效的提高听课质量效率?

课堂是学生获得知识的主要渠道&#xff0c;课堂听课效率是会影响到学习效果的&#xff0c;听课质量是关系着学生学习成绩好和坏的因素之一&#xff0c;那怎样提高听课效率&#xff1f; 第一、养成课前预习。学生课前不预习&#xff0c;缺乏知识准备&#xff0c;容易导致上课听不…

Python 整数类型(int)详解:无限范围与多种进制

引言 在编程中&#xff0c;整数是最基本的数据类型之一。不同编程语言对整数的处理方式各不相同&#xff0c;这往往影响到程序的性能和开发者的选择。本文将深入探讨 Python 中的整数类型&#xff08;int&#xff09;&#xff0c;其独特的处理方式&#xff0c;以及它在日常编程…

Ubuntu24 文件目录结构——用户——权限 详解

目录 权限 用户 文件目录结构 一个目录可以有程序&#xff0c;目录&#xff0c;文件&#xff0c;以及这三者的链接。可以看到还分别有使用者和权限信息。 每个文件和目录都有与之关联的三个主要属性&#xff1a;所有者&#xff08;owner&#xff09;、组&#xff08;group&a…

软件工程期末复习(3)

软件生命周期 一般问题的解决过程&#xff1a; 问题的阐述&#xff1a;界定问题&#xff0c;用较宽的范围而不是细节来定义和描述待解问题&#xff1b; 问题的分析&#xff1a;问题定义的提炼&#xff0c;把问题分成可以理解和处理的子问题&#xff0c;进而提供基本细节&…

小区物业管理系统

文章目录 小区物业管理系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 小区物业管理系统 一、项目演示 小区物业管理系统 二、项目介绍 基于springbootvue的前后端分离物业管理系统 系统角…

Java锁事

1.1 大厂面试题 一、Synchronized相关问题 1.Synchronized 用过吗&#xff0c;其原理是什么? 2.你刚才提到获取对象的锁&#xff0c;这个“锁”到底是什么?如何确定对象的领? 3.什么是可重入性&#xff0c;为什么说Synchronized是可重入锁? 4.JVM对Java的原生锁做了哪些优化…

到底什么是ASIC和FPGA?

ASIC&#xff08;Application Specific Integrated Circuit&#xff0c;应用特定集成电路&#xff09;和FPGA&#xff08;Field Programmable Gate Array&#xff0c;现场可编程门阵列&#xff09;都是集成电路&#xff08;IC&#xff09;的重要类型&#xff0c;它们在电子设计…

上海市计算机学会竞赛平台2022年3月月赛丙组正负数判断

题目描述 给定一个整数 &#x1d45b;n&#xff0c;若 &#x1d45b;n 为正数&#xff0c;输出 Positive&#xff0c;若 &#x1d45b;n 为负数&#xff0c;输出 Negative&#xff0c;若 &#x1d45b;n 恰好为零&#xff0c;输出 Zero。 输入格式 单个整数&#xff1a;表示…

Ubuntu 24 换国内源及原理 (阿里源 清华源 中科大源 网易源)

备份原文件 sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak 编辑源文件 sudo gedit /etc/apt/sources.list.d/ubuntu.sources 粘贴到文本&#xff08;其中一个即可&#xff09;&#xff1a; &#xff08;阿里源&#xff09…

数据结构与算法学习笔记之线性表三---顺序表的动态分配存储表示和实现(C++)

目录 前言 1.顺序表的动态分配存储表示 2.顺序表的静态存储表示 1.初始化 2.销毁 3.清空 4.判空 5.表长 6.数据元素 7.获取下标 8.前驱节点 9.后继节点 10.插入 11.删除 12.遍历 13.测试代码 前言 这篇文章讲的是线性表的动态分配存储表示。 1.顺序表的…

【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第十三篇&#xff1a;volatile关键字讲解。 在 Java 中&#xff0c;volatile关键字是一种轻量级的同步机制&#xff0c;用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及…

买卖股票的最佳时机 II(LeetCode 122)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

react组件渲染性能优化之函数组件-memo使用

函数组件赋值相同的值视图不会渲染&#xff0c;类组件会&#xff0c;因为函数组件默认就阻止了 import {useState} from react export default function App() {const [counter, setCounter] useState(1)console.log(App组件渲染了);return(<div><h1>{counter}&l…

已解决java.lang.AbstractMethodError: 抽象方法错误的正确解决方法,亲测有效!!!

已解决java.lang.AbstractMethodError: 抽象方法错误的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 更新和重新编译依赖 确认类和接口的版本一致性 类加载器配置检查 总结 问题分析 java.lang.…

防城港知识付费系统,教学活动在设计中需要注意什么?如何进行教学设计?

老师们的教学能否让学生学到知识&#xff0c;让学生懂得书本上的道理&#xff0c;那么教学活动很重要&#xff0c;因此在设计的时候&#xff0c;一定要根据教学的目的以及孩子的特点来进行设计。 假设老师为学生进行美术绘画的教学活动设计&#xff0c;那么需要注意以下三个方面…