C++设计模式_行为型模式_迭代器模式Iterator

本文记录迭代器模式。

容器和迭代器的简单范例

举出C++中vector 和 list中迭代器的使用方法。

cpp 复制代码
void test()
{
	// 1  容器和迭代器简单示例:vector 和 List
	vector<int> msgVector;
	msgVector.push_back(1);
	msgVector.push_back(2);
	msgVector.push_back(3);	

	for (std::vector<int>::iterator it = msgVector.begin(); it != msgVector.end(); ++it)
	{
		cout << *it << endl;
	}
	/*
	1
	2
	3
	*/
	
	// 2 list 
	list<int> msgList;
	msgList.push_back(1);
	msgList.push_back(2);
	msgList.push_front(3);
	for (list<int>::iterator it = msgList.begin(); it != msgList.end(); ++it)
	{
		cout << *it << endl;
	}
	/*
	3
	1
	2
	*/

}

单一职责原则---原则7

单一职责原则的定义

单一职责原则定义:一个类应该只有一个引起变化的原因,通俗来讲,就是一个类的职责应该单一,应该只做一类事情或者对外提供一种功能。例如,上边的列子中,如果将vector的容器和迭代器都放在一个类中实现,如果在从头到尾 遍历基础上,再次增加从尾到头的遍历,就会非常不便。反之,如果将迭代器和容器分离实现,那么在迭代器中增加从尾部到头的遍历就不会影响到容器,这样的设计方式提高了程序的可维护性。

内聚与耦合

内聚性用于衡量一个模块内部各组成部分之间彼此结合紧密程度,是指从功能角度来衡量模块内的联系。当一个模块被设计成只支持一组相关的功能时,就称它具有高内聚;反之,如果设计成一组不相关的功能时,称之为低内聚。

耦合性:模块之间的相互关联的程度,取决于两者的接口的复杂程度,相互之间的调用方式,以及调用时哪些信息需要交互。耦合性分为如下几种类型:

(1) 内容耦合--当一个模块直接修改或操作另一个模块的数据或一个模块不通过正常入口而转入另一个模块时,称为内容耦合。内容耦合的耦合程度最高,应避免使用。

(2) 公共耦合--两个或两个以上的模块共同引用一个全局数据项(全局数据结构、共享的通信区、内存的公共覆盖区等),称为公共耦合。在具有大量公共耦合的结构中,确定哪个模块对全局数据项进行了操作十分困难。

(3) 外部耦合一-一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,称为外部耦合。

(4) 控制耦合一一个模块通过传送开关、标志、名字等控制信息(统称控制信号),明显地控制选择另一模块的功能,称为控制耦合。

(5) 标记耦合一指两个模块间传递的是数据结构,例如,高级语言中的数组名、记录名、文件名等,其实传递的是该数据结构的地址。

(6) 数据耦合一-模块之间通过参数传递数据,称为数据耦合。数据耦合的程度最低,这种耦合方式大量存在于程序代码中,例如,程序中往往需要将某些模块的输出数据(返回结果)作为另一些模块的输入数据(通过参数传递)。

耦合性影响软件的复杂程度和设计质量,如果模块间必须存在耦合,那么尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合.

从整体而言,程序设计讲究的高内聚、低耦合, 如下图所示,一个类职责越单一,内聚度就越高,而要达到低耦合的目的,也要尽量遵循依赖倒置原则-高层组件和低层组件都依赖子抽象层或者说尽量使用抽象耦合来代替具体耦合。

迭代器模式的范例

迭代器模式范例

下面代码实现一个迭代器。

cpp 复制代码
namespace _nsp1
{
	// 抽象迭代器类模板, 所有迭代器都要继承这个类
	template<typename T>
	class MyIter
	{
	public:
		virtual void First() = 0; // 第一个元素
		virtual void Next() = 0; // 下一个元素
		virtual bool IsDone() = 0; // 是否到结尾
		virtual T&	 CurrentItem() = 0; // 当前元素
		virtual ~MyIter()
		{
			cout << "~myIter()" << endl;
		}
	};

	// 实现一个Container类,专门用于存放数据
	template<typename T>
	class MyContainer
	{
	public:
		virtual MyIter<T>* CreateIter() = 0;  // 创建迭代器
		virtual T& getItem(int index) = 0; // 获取元素
		virtual int getSize() = 0; // 获取元素个数
		virtual ~MyContainer()
		{
			cout << "~MyContainer()" << endl;
		}
	};


	// 实现vector迭代器,专门用于遍历vector
	template<typename T>
	class MyVectorIter : public MyIter<T>
	{
	public:
		MyVectorIter(MyContainer<T>* vec) : m_myvector(vec), m_currentIndex(0) {}
		
		virtual void First()
		{
			m_currentIndex = 0;
		}
		virtual void Next()
		{
			if (m_currentIndex < m_myvector->getSize())
			{
				m_currentIndex++;
			}
		}
		virtual bool IsDone()
		{
			return m_currentIndex == m_myvector->getSize();
		}
		virtual T& CurrentItem()
		{
			return m_myvector->getItem(m_currentIndex);
		}
	private:
		MyContainer<T>* m_myvector; // 保存容器
		int				m_currentIndex; // 保存当前索引
	};

	// 创建一个具体的vector容器
	template<typename T>	
	class MyVector : public MyContainer<T>
	{
	public:
		MyVector()
		{
			// 初始化数据
			for (int i = 0; i < 10; ++i)
			{
				m_data[i] = i;
			}
		}

		virtual MyIter<T>* CreateIter()
		{
			// 工厂模式,实参传递是容器本身
			return new MyVectorIter<T>(this);
		}

		virtual T& getItem(int index)
		{
			return m_data[index];
		}

		virtual int getSize()
		{
			return 10;			// 为了简化代码,将容器实现为固定的大小的数组
		}
	private:
		// 为了 简化代码,将容器实现为固定的大小的数组
		T m_data[10];
	};

	void test()
	{
		MyContainer<int>* pvec = new MyVector<int>();
		MyIter<int>* piter = pvec->CreateIter();
		for (piter->First(); !piter->IsDone(); piter->Next())
		{
			cout << piter->CurrentItem() << endl;
		}
		delete pvec;
		delete piter;
	
	}
}

UML

迭代器模式的uml图:

UML图的四种角色:

(1) Iterator(抽象迭代器): 用于定义访问和遍历容器中元素的接口。这里指 myIter类模板。

(2) Concretelterator(具体选代器): 实现了抽象迭代器的接口,完成对聚合对象(容器)中元素的遍历,记录当前元素的位置。这里指 MyVetorIter 类模板。

(3) Aggregate(抽象聚合): 将聚合理解成容器。用于存储和管理元素对象,声明一个Createlterator 方法用于创建一个迭代器对象充当创建选代器的工厂角色。这里指MyContainer 类模板。

(4) ConcreteAggregate(具体聚合): 实现了抽象聚合的 CreateIterator 方法以创建相应的迭代器,该方法返回 ConcreteIterator 的一个适当的实例。这里指 MyVector类模板。

相关推荐
白衣鸽子3 小时前
【基础数据篇】数据遍历大师:Iterator模式
后端·设计模式
muxin-始终如一3 小时前
系统重构过程以及具体方法
设计模式·重构
FL16238631294 小时前
C++基于opencv实现的暗通道的先验图像去雾
c++·opencv·计算机视觉
仰泳的熊猫4 小时前
LeetCode:538. 把二叉搜索树转换为累加树/1038. 从二叉搜索树到更大和树
数据结构·c++·算法·leetcode
kyle~4 小时前
C++---向上取整
开发语言·c++
小龙报5 小时前
《算法通关指南---C++编程篇(1)》
开发语言·c++·程序人生·算法·学习方法·visual studio
Cx330❀5 小时前
《C++ 手搓list容器底层》:从结构原理深度解析到功能实现(附源码版)
开发语言·数据结构·c++·经验分享·算法·list
仰泳的熊猫5 小时前
LeetCode:98. 验证二叉搜索树
数据结构·c++·算法·leetcode
暴力求解5 小时前
C++ --- 模版初阶
c++