Iterator 迭代器
意图
提供一种方法顺序访问一个聚合对象中各个元素 , 而又不需暴露该对象的内部表示。
动机
一个聚合对象, 如列表(list), 应该提供一种方法来让别人可以访问它的元素,而又不需暴露它的内部结构
迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟踪当前的元素 ;即, 它知道哪些元素已经遍历过了。
适用性
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 支持对聚合对象的多种遍历。
- 为遍历不同的聚合结构提供一个统一的接口 (即, 支持多态迭代)。
结构
定义一个抽象列表类AbstractList,它提供操作列表的公共接口。类似地,我们也需要一个抽象的迭代器类Iterator,它定义公共的迭代接口。然后我们可以为每个不同的列表实现定义具体的Iterator子类。这样迭代机制就与具体的聚合类无关了。

参与者
Iterator:迭代器定义访问和遍历元素的接口。
ConcreteIterator:具体迭代器实现迭代器接口;对该聚合遍历时跟踪当前位置。
Aggregate:聚合定义创建相应迭代器对象的接口。
ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteAggregate的一个适当的实例。
效果
- 访问一个聚合对象的内容而无需暴露它的内部表示;
- 支持对聚合对象的多种遍历(从前到后,从后到前);
- 为遍历不同的聚合结构提供一个统一的接口,即支持多态迭代。
实现
#include <iostream>
using namespace std; typedef struct tagNode
{
int value;
tagNode *pNext;
}Node; class JTList
{
public:
JTList() : m_pHead(NULL), m_pTail(NULL){};
JTList(const JTList &);
~JTList();
JTList &operator=(const JTList &); long GetCount() const;
Node *Get(const long index) const;
Node *First() const;
Node *Last() const;
bool Includes(const int &) const; void Append(const int &);
void Remove(Node *pNode);
void RemoveAll(); private:
Node *m_pHead;
Node *m_pTail;
long m_lCount;
}; class Iterator
{
public:
virtual void First() = ;
virtual void Next() = ;
virtual bool IsDone() const = ;
virtual Node *CurrentItem() const = ;
}; class JTListIterator : public Iterator
{
public:
JTListIterator(JTList *pList) : m_pJTList(pList), m_pCurrent(NULL){} virtual void First();
virtual void Next();
virtual bool IsDone() const;
virtual Node *CurrentItem() const; private:
JTList *m_pJTList;
Node *m_pCurrent;
}; JTList::~JTList()
{
Node *pCurrent = m_pHead;
Node *pNextNode = NULL;
while (pCurrent)
{
pNextNode = pCurrent->pNext;
delete pCurrent;
pCurrent = pNextNode;
}
} long JTList::GetCount()const
{
return m_lCount;
} Node *JTList::Get(const long index) const
{
// The min index is 0, max index is count - 1
if (index > m_lCount - || index < )
{
return NULL;
} int iPosTemp = ;
Node *pNodeTemp = m_pHead;
while (pNodeTemp)
{
if (index == iPosTemp++)
{
return pNodeTemp;
}
pNodeTemp = pNodeTemp->pNext;
}
return NULL;
} Node *JTList::First() const
{
return m_pHead;
} Node *JTList::Last() const
{
return m_pTail;
} bool JTList::Includes(const int &value) const
{
Node *pNodeTemp = m_pHead;
while (pNodeTemp)
{
if (value == pNodeTemp->value)
{
return true;
}
pNodeTemp = pNodeTemp->pNext;
}
return false;
} void JTList::Append(const int &value)
{
// Create the new node
Node *pInsertNode = new Node;
pInsertNode->value = value;
pInsertNode->pNext = NULL; // This list is empty
if (m_pHead == NULL)
{
m_pHead = m_pTail = pInsertNode;
}
else
{
m_pTail->pNext = pInsertNode;
m_pTail = pInsertNode;
}
++m_lCount;
} void JTList::Remove(Node *pNode)
{
if (pNode == NULL || m_pHead == NULL || m_pTail == NULL)
{
return;
} if (pNode == m_pHead) // If the deleting node is head node
{
Node *pNewHead = m_pHead->pNext;
m_pHead = pNewHead;
}
else
{
// To get the deleting node's previous node
Node *pPreviousNode = NULL;
Node *pCurrentNode = m_pHead;
while (pCurrentNode)
{
pPreviousNode = pCurrentNode;
pCurrentNode = pCurrentNode->pNext;
if (pCurrentNode == pNode)
{
break;
}
} // To get the deleting node's next node
Node *pNextNode = pNode->pNext; // If pNextNode is NULL, it means the deleting node is the tail node, we should change the m_pTail pointer
if (pNextNode == NULL)
{
m_pTail = pPreviousNode;
} // Relink the list
pPreviousNode->pNext = pNextNode;
} // Delete the node
delete pNode;
pNode = NULL;
--m_lCount;
} void JTList::RemoveAll()
{
delete this;
} void JTListIterator::First()
{
m_pCurrent = m_pJTList->First();
} void JTListIterator::Next()
{
m_pCurrent = m_pCurrent->pNext;
} bool JTListIterator::IsDone() const
{
return m_pCurrent == m_pJTList->Last()->pNext;
} Node *JTListIterator::CurrentItem() const
{
return m_pCurrent;
} int main()
{
JTList *pJTList = new JTList;
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append();
pJTList->Append(); Iterator *pIterator = new JTListIterator(pJTList); // Print the list by JTListIterator
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
cout << pIterator->CurrentItem()->value << "->";
}
cout << "NULL" << endl; // Test for removing
Node *pDeleteNode = NULL;
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
pDeleteNode = pIterator->CurrentItem();
if (pDeleteNode->value == )
{
pJTList->Remove(pDeleteNode);
break;
}
} // Print the list by JTListIterator
for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
{
cout << pIterator->CurrentItem()->value << "->";
}
cout << "NULL" << endl; delete pIterator;
delete pJTList; return ;
}
Iterator 迭代器的更多相关文章
- ES6笔记(6)-- Set、Map结构和Iterator迭代器
系列文章 -- ES6笔记系列 搞ES6的人也是够无聊,把JS弄得越来越像Java.C++,连Iterator迭代器.Set集合.Map结构都出来了,不知道说什么好... 一.简单使用 1. iter ...
- vector容器+iterator迭代器
关于vector容器的详细描述,可参考:http://www.jb51.net/article/41648.htm 关于iterator迭代器的描述,可参考http://www.cppblog.c ...
- C++ Iterator迭代器介绍及Iterator迭代器用法代码举例
C++ Iterator迭代器介绍 迭代器可被用来访问一个容器类的所包函的全部元素,其行为像一个指针.举一个例子,你可用一个迭代器来实现对vector容器中所含元素的遍历.有这么几种迭代器如下: 迭代 ...
- 【转】Java学习之Iterator(迭代器)的一般用法 (转)
[转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...
- 设计模式(十五):Iterator迭代器模式 -- 行为型模式
1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用 ...
- C#:iterator 迭代器/partial class 分布类/泛型
C#:iterator 迭代器/partial class 分布类/泛型 iterator 迭代器 写个最简单的迭代,(迭代一个字符串数组): 1.实现接口中的方法: 1 using System; ...
- [设计模式] Iterator - 迭代器模式:由一份奥利奥早餐联想到的设计模式
Iterator - 迭代器模式 目录 前言 回顾 UML 类图 代码分析 抽象的 UML 类图 思考 前言 这是一包奥利奥(数组),里面藏了很多块奥利奥饼干(数组中的元素),我将它们放在一个碟子上慢 ...
- Python 中 Iterator(迭代器)和Iterable(迭代对象)的区别
直接可以用作for循环的数据类型有以下几种: tuple.list.dict.str等, 上述数据类型可以用作for循环的叫做可迭代对象Iterable.可以使用isinstance判断一个对象是否是 ...
- 使用Iterator迭代器循环集合
1.Iterator迭代器用于遍历集合元素,获取迭代器可以使用. 2.Iterator提供了统一遍历集合元素的 方式 ,其提供了用于遍历集合的连个方法----- boolean hasNext()判 ...
- [C# 设计模式] Iterator - 迭代器模式:我与一份奥利奥早餐的故事
Iterator - 迭代器模式 目录 前言 回顾 UML 类图 代码分析 抽象的 UML 类图 思考 前言 这是一包奥利奥(数组),里面藏了很多块奥利奥饼干(数组中的元素),我将它们放在一个碟子上慢 ...
随机推荐
- LINUX 线程
1.使用进程技术的优势(1)CPU时分复用,单核心CPU可以实现宏观上的并行(2)实现多任务系统需求(多任务的需求是客观的)2.进程技术的劣势(1)进程间切换开销大(2)进程间通信麻烦而且效率低3.解 ...
- CIDR 无类别域间路由
参考百度百科 1.全称 CIDR的全称是Classless Inter-Domain Routing 2.作用 CIDR将路由集中起来,使一个IP地址代表主要骨干提供商服务的几千个IP地址,从而减轻I ...
- openstack组件的数据库操作
一.基础 SQLAlchemy http://docs.sqlalchemy.org/en/rel_0_9/index.html 对数据库进行操作的工具:xxx-manage db ... 二.数据库 ...
- C\C++中 fopen中文件打开方式的区别:
在C语言中,大家常用到fopen打开文件,准备进行写操作,再用fwrite把数据写入文件,最后用fclose关闭文件. 如以下C代码: #include <stdio.h> char ...
- Git之修复Bug流程
场景描述 当一个项目已经上线,同时又在原有基础上新增功能模块,于是乎就要在原有代码的基础上进行开发,在新增模块功能的开发的过程中,项目发现了一个紧急Bug,需要修复.应对这种情况,有以下两种解决方案: ...
- 获取assets文件内容,raw内容
1.均采用流的方式获取里面的内容 assets context.getAssets().open(“fileName”); raw InputStream inputStream = context. ...
- Windows服务的安装和卸载
## install %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe ***Cache.WinService.exe # ...
- 列表函数&方法
列表(list)的基本操作,方法及属性.
- 一个罕见的MSSQL注入漏洞案例
一个罕见的MSSQL注入漏洞案例 这里作者准备分享一个在去年Google赏金计划中发现的相当罕见漏洞,也是作者在整个渗透测试生涯中唯一一次遇到的. 目标网站使用了微软 SQL Server 数据库并且 ...
- LCD时序中设计到的VSPW/VBPD/VFPD/HSPW/HBPD/HFPD总结【转】
转自:https://blog.csdn.net/u011603302/article/details/50732406 下面是我在网上摘录的一些关于LCD信号所需时钟的一些介绍, 描述方式一: 来自 ...