迭代器模式c++实现

2023-11-01

参考书籍《Head First设计模式》

需求场景

           餐馆和咖啡馆的菜单分别是用数组和容器(vector)存储的,有一天餐馆和咖啡店合并了想要打印菜单,必须实现两个不同的遍历(数组用sizeof计算长度,用[]取元素;容器用size取长度,用at()取元素),来处理两种不同的聚合类型,代码类似于下面所示

 

	for (int i = 0; i<sizeof(dinerMenu.items_) / sizeof(dinerMenu.items_[0]); i++)
	{
		MenuItem item = dinerMenu.items_[i];
		std::cout << item.name <<","<< item.description << ","<< item.price << std::endl;
	}

	for (int i = 0; i<conffeMenu.items_.size(); i++)
	{
		MenuItem item = conffeMenu.items_.at(i);
		std::cout << item.name << "," << item.description << "," << item.price <<std::endl;
	}

       如果我们还要遍历另外一种聚合数据,比如map,那么就要再加一种遍历方法。又或者我们有一天咖啡店不用容器存储,改用数组了,那我们的遍历方法又要改写。这就要求客户端对聚合的实现很了解,即针对实现编程(而我们提倡的设计原则是针对接口编程,而不是针对实现编程)。

     在上述例子中引起变化的是:由不同的组合类型所造成的遍历。那我们可以封装遍历吗?迭代器模式就是封装了遍历。迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

模式定义

        迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部表示。

        类图如下

        


       

代码实现

         

         如上面需求场景中,我们使用迭代器模式,让两个具体的聚合类(餐馆和咖啡馆)都提供一个createIterator的接口,客户端使用该接口返回的iterator遍历聚合体中各元素。这样客户端不需要关系聚合体的具体实现,针对不同聚合体提供的iterator使用方法一样。

         先定义迭代器接口(抽象类Iterator)

     

class Iterator {
public:
	virtual bool hasNext() = 0;
	virtual void* next() = 0;
};

两个具体的迭代器:餐厅菜单迭代器和咖啡店菜单迭代器

class CoffeMenuIterator :public Iterator {
public:
	CoffeMenuIterator(std::vector< MenuItem>* items) :items_(items), position_(0)
	{
		
	}
	virtual MenuItem& next()override
	{
		MenuItem& item = items_->at(position_);
		position_++;
		return item;
	}
	bool hasNext()override
	{
		if (position_ >= items_->size())
		{
			return false;
		}
		else
		{
			return true;
		}
	}
private:
	std::vector< MenuItem>* items_;
	int position_;
};

class DinerMenuIterator :public Iterator {
public:
	DinerMenuIterator(MenuItem items[],int length) :items_(items), position_(0),length_(length)
	{
		
	}
	virtual MenuItem& next()override
	{
		MenuItem& item = items_[position_];
		position_++;
		return item;
	}
	bool hasNext()override
	{
		if (position_ >= length_)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
private:
	MenuItem* items_;
	int position_;
	int length_;
};

        再实现两个具体的聚合类,针对该例子即实现餐馆菜单和咖啡店菜单(它们都要实现createIterator接口)。

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

class DinerMenu :public Menu {
public:
	DinerMenu()
	{
		items_[0] = { "红烧肉","红烧肉,肥瘦相间,香而不腻",32 };
		items_[1] = { "西红柿炒鸡蛋","西红柿炒鸡蛋,国民妈妈菜",15 };
		items_[2] = { "土豆丝","土豆丝,超便宜",12 };
	}
	virtual Iterator* createIterator() override {
		return new DinerMenuIterator(items_,3);
	}
private:
	MenuItem items_[3];
};

class CoffeMenu :public Menu {
public:
	CoffeMenu()
	{
		items_.push_back({ "拿铁","拿铁,好喝",18 });
		items_.push_back({ "卡布奇诺","卡布奇诺卡布奇诺",18 });
		items_.push_back({ "意式浓缩咖啡","意式浓缩咖啡",22 });
	}
	virtual Iterator* createIterator() override {
		return new CoffeMenuIterator(&items_);
	}
private:
	std::vector< MenuItem> items_;
};

   运行测试效果如下

   

        


       

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

迭代器模式c++实现 的相关文章

随机推荐

  • Qtcreator常用快捷键

    qtcreator常用快捷键 1 代码补全 2 切换已打开的文件 3 快速添加方法实体 cpp 声明 4 修改变量名 并应用到所有使用该变量的地方 5 快速打开输出窗口 6 快速切换模式 7 书签功能 8 分栏显示 9 快速重写父类方法 1
  • python学习笔记---正则表达式【廖雪峰】

    正则表达式 正则表达式是一种用来匹配字符串的强有力的武器 它的设计思想是用一种描述性的语言来给字符串定义一个规则 凡是符合规则的字符串 我们就认为它 匹配 了 否则 该字符串就是不合法的 我们判断一个字符串是否是合法的Email的方法是 创
  • Linux-0.12内核打开文件过程--sys_open源码分析

    上图展示了进程打开文件使用的内核数据结构 所以要打开文件 就要构造上图中的关系 int sys open const char filename int flag int mode struct m inode inode struct f
  • js逆向教程1:某某威客登录

    假设不会js语法来进行js破解 本文感谢挖掘机小王子提供的帮助 挖掘机小王子的github https github com EnjoyScraping 网站的登录接口 我们可以准备一组常用的账号密码 并记下对应的MD5 base64等密文
  • 如何计算无线天线长度

    天线长度为波长的1 4 波长 波速 频率 波速 光速 3 100000000 eg 频率为476 3 则天线长度 300 476 3 4 0 1574 m
  • 洛谷 P2249 【深基13.例1】查找

    题目链接 https www luogu com cn problem P2249 include
  • Nginx极简使用

    编译源码安装Nginx 确认系统版本 确认网络 确认yum可用 确认防火墙 确认SELinux 并关闭 安装依赖库和运行环境 下载安装Nginx Nginx源码编译 查看目录结构 生成编译文件makefile 编译 安装 展示nginx的目
  • 【HTSl】A系统开发总结~致敬这热烈的夏季

    2019的六七八月 我陪伴着A系统一起走过这个炎热的夏季 从单一的功能 完成了华丽的蜕变 迎来了我们的成长 经过历时将近两个月的紧张开发 终于迎来了A系统上线 疲惫的身体得到的暂时的缓解 会想这一个月的开发 感觉收获很多 抱怨也很多 在这个
  • SpringBoot2.7.2 版本配置swagger3的方法及教程

    原因 对SpringBoot2 7 2版本 swagger2 x版本不再适用 所以就选择了swagger3版本 但是相较于swagger2版本 swagger3版本更加麻烦 具体教程如下 方法 第一步 引入依赖
  • 【计算机毕业设计】java ssm在线学习系统 在线学习平台

    毕设帮助 源码交流 技术解答 见文末 一 前言 以前 我们的在线学习主要是通过面对面的讲授 这样 有很多优势 教师可以与学生直接交流 但是也有许多不尽人意的地方 课堂在线学习很大程度上受到时间和空间的限制 浪费了在线学习资源同时对于学生的进
  • 【算法题目】Leetcode算法题思路:两数相加

    在LeetCode上刷了一题比较基础的算法题 一开始也能解出来 不过在解题过程中用了比较多的if判断 看起来代码比较差 经过思考和改进把原来的算法优化了 题目 给出两个 非空 的链表用来表示两个非负的整数 其中 它们各自的位数是按照 逆序
  • 数据结构(C#)-- 贪心算法解决背包问题

    using System using System Collections Generic using System Linq using System Text using System Data using System Collect
  • 计算机的基本组成及工作原理

    计算机的基本组成及工作原理 1 3 1 计算机系统的组成 计算机系统是由硬件系统和软件系统两大部分组成 这一节将分别介绍计算机硬件系统和软件系统 计算机硬件是构成计算机系统各功能部件的集合 是由电子 机械和光电元件组成的各种计算机部件和设备
  • pytorch: Pool 和 AdaptivePool 的区别和使用方法

    在 pytorch 中 池化层 Pooling 有两种操作方式 一种是手动设计 另一种是自适应池化 一 手动设计 池化层操作 一般有最大值 max 池化和均值 avg 池化 而根据尺寸又有一维 二维 三维 所以 手动设计的池化层有6种函数
  • GitHub加速教程

    转载 GitHub 加速教程 GitHub Hosts 仓库提供最新的GitHub hosts地址 你可以自行配置hosts 但是最佳实践是使用 SwitchHosts 管理你的 hosts 可以阅读文章 SwitchHosts 还能这样管
  • 在Java中尽量使用包装类Integer而不使用int

    1 在MySQL中没有给字段赋值默认为null 当你从数据库中查出来也是null 如果该字段在对应的Java代码中是int类型 null不能对应int类型 因为int代表的是基本数据类型 只能是基本的数字 2 实体类的属性你可以给它赋值也可
  • 三分钟教你学Git(二十一) - 复制连续多个提交

    有时候我们有一个分支A 里边包含了提交A1 gt A2 gt A3 gt A4 gt A5等 然后我们又有一个分支B 里边包含了提交A1 gt A2 gt B1 gt B2 gt B3 现在我们想把分支A中的A3 A4 A5版本复制到分支B
  • vue3项目实战+element-plus

    记录自己搭建前端项目的学习过程和开发过程 希望一起学习进步 采用Vue3 element plus axios vue router sass 目前刚开始是用到了这些 随着开发慢慢更新 npm是比较慢的 所以我用的是pnpm 安装指令 np
  • 播放raw下的音乐文件

    在开发的过程中 我们需要一些不需要用户改变的音乐或图像文件 这些文件存在安卓res raw文件夹中 下面就介绍如何播放res raw文件夹中的乐 1 在res目录下新建一个raw文件夹 2 界面上 xml文件中有一个按钮控件 当我们点击按钮
  • 迭代器模式c++实现

    参考书籍 Head First设计模式 需求场景 餐馆和咖啡馆的菜单分别是用数组和容器 vector 存储的 有一天餐馆和咖啡店合并了想要打印菜单 必须实现两个不同的遍历 数组用sizeof计算长度 用 取元素 容器用size取长度 用at