设计模式 笔记 迭代器模式 Iterator
//---------------------------15/04/26----------------------------
//Iterator 迭代器模式----对象行为型模式
/*
1:意图:
提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
2:别名:
游标(Cursor)
3:动机:
4:适用性:
1>访问一个聚合对象的内容而无需暴露它的内部表示。
2>支持对聚合对象的多种遍历。
3>为遍历不同的聚合结构提供一个统一的接口。
5:结构:
Aggregate:<-------------Client----------------->Iterator:
CreateIterator() First()
| Next()
| IsDone()
| CurrentItem()
| |
ConcreteAggregate()- - - - - - - - - - - - - ->ConcreteIterator
CreateIterator() <------------------------------|
{ return new ConcreteIterator(this)}
6:参与者:
1>Iterator:
迭代器定义访问和遍历元素的接口。
2>ConcreteIterator:
1)具体迭代器实现迭代器接口。
2)对该聚合遍历时跟踪当前位置。
3>Aggregate:
聚合定义创建相应迭代器对象的接口。
4>ConcreteAggregate:
具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。
7:协作:
ConcreteIterator跟踪聚合中的当前对象,并能够计算出代遍历的后继对象。
8:效果:
1>它支持以不同的方式遍历一个聚合:
复杂的聚合可用多种方式进行遍历。比如stl中的正常的迭代器以及反向迭代器。
2>迭代器简化了聚合的接口:
有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口,这样就简化了聚合的接口。
3>在同一个聚合上可以有多个遍历:
每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。
9:实现:
迭代器在实现上有许多变化和选择。
1>谁控制该迭代:
由客户来控制迭代的称为外部迭代器,由迭代器控制迭代称为内部迭代器。外部迭代器比较灵活
内部迭代器实现起来比较简单。所以能实现还是实现为外部迭代器的。
2>谁定义遍历算法:
迭代器来负责遍历算法易于在相同聚合上使用不同的迭代算法,也易于在不同的聚合上重用相同的算法。
但是因为要访问聚合中的私有变量,会破坏聚合的封装性
3>迭代器健壮程度如何:
插入和删除操作不能干扰别的迭代器的遍历。为了速度考虑,stl的迭代器并不都能保证这个条件。
4>附加的迭代器操作:
迭代器起码要有First,Next,IsDone,CurrenItem等操作,当然可以附加一些有用的操作,比如
Previous
5>在c++中使用多态的迭代器:
使用多态的迭代器是要付出代价的,也就是客户必须自己删除迭代器指针,所以可以使用智能指针
也就是代理模式。
6>迭代器可有特权访问:
迭代器可以访问聚合的元素,所以可以声明为友元,为了防止多次声明友元,可以定义一个abstract
的迭代器,然后由只要继承这个类就能行了。
7>用于复合对象的迭代器:
在Composite模式中,那些递归聚合结构上,外部迭代器难以实现,因为该结构中不同对象处于嵌套
聚合的多个不同层次,因此一个外部迭代器为跟踪对象必须存储一条纵贯该composite的路径。
8>空迭代器:
一个空迭代器是一个退化的迭代器,它可以帮助处理边界条件,也就是stl中的end()。
` 10:代码示例: */
//Aggregate:定义了一些接口
template<class Item>
class List
{
public:
List(long size= DEFAULT_LIST_CAPACITY);
long Count() const;
Item& Get(long index)
const;
};
//abstract Iterator:定义迭代器的接口
template<class Item>
class Iterator
{
public:
virtual void First() =
;
virtual void Next() =
;
virtual bool IsDone()
;
virtual Item CurrenItem()
const = ;
protected:
Iterator();
};
//ConcreteIterator:
template<class Item>
class ListIterator :
public Iterator<Item>
{
public:
ListIterator(const List<Item>* aList);
virtual void First();
virtual void Next();
virtual bool IsDone()
const;
virtual Item CurrenItem()
const;
private:
const List<Item>* _list;
long _current;
}
//只要把当前的位置设置为0就是第一个
template<class Item>
void ListIterator<Item>::First()
{
_current =
;
}
//下一个就是把位置加一
template<class Item>
void ListIterator<Item>::Next()
{
_current++;
}
//如果完成了,说明当前位置大于等于list中的元素了
template<class Item>
bool ListIterator<Item>::IsDone()
const
{
return _current >= _list->Count();
}
//只要当前的位置小于元素数量,就返回当前元素。
template<class Item>
Item ListIterator<Item>::CurrenItem()
const
{
if(IsDone())
throw IteratorOutofBounds;
return _list->Get(_current);
}
//这是一个客户自定义打印函数
void PrintEmployees(Iterator<Employee*>& i)
{
for(i.First(); !i.IsDone(); i.Next())
i.CurrenItem()->Print();
}
//定义一个指向指针list
List<Employee*>* employee;
//...
//定义迭代器
ListIterator<Employee*> forward(employee);
ReverseListIterator<Employee*> backward(employee);
PrintEmployees(forward);
PrintEmployees(backward);
//这是一个不同的list,但是客户需要记住不同的迭代器,会很麻烦,所以我们需要在list
//中实现一个工厂方法,它能直接返回一个abstract类型的迭代器。
SkipList<Employee*>* employees;
//...
SkipListIterator<Employee*> Iterator(employees);
PrintEmployees(iterator);
//抽象的list
template<class Item>
class AbstractList
{
public:
virtual Iterator<Item>* CreateIterator()
const = ;
};
template<class Item>
Iterator<Item>* List<Item>::CreateIterator()
const
{
return new ListIterator<Item>(this);
}
//这样可以不使用具体迭代器类型,直接使用list对象的create函数来创造一个迭代器。
AbstractList<Employee*>* employee;
Iterator<Employee*>* iterator = employee->CreateIterator();
PrintEmployees(*iterator);
delete iterator;
//为了保证迭代器被删除,可以使用智能指针
template<class Item>
class IteratorPtr
{
public:
IteratorPtr(Iterator<Item>* i): _i(i){}
_IteratorPtr(){delete _i};
//每个智能指针都要实现的两个重载
Iterator<Item>*
operator->() { return _i;}
Iterator<Item>*
operator*() { return *_i;}
private:
IteratorPtr(const IteratorPtr&);
IteratorPtr&
operator=(const IteratorPtr&);
private:
Iterator<Item>* _i;
};
//这样就不需要delete了。
AbstractList<Employee*>* employee;
IteratorPtr<Employee*>* iterator = employee->CreateIterator();
PrintEmployees(*iterator);
//一个内部的ListIterator:
遍历操作在内部实现
template<class Item>
class ListTraverser
{
public:
ListTraverser(List<Item>* aList);
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) =
;
private:
ListIterator<Item> _iterator;
};
template<class Item>
ListTraverser<Item>::ListTraverser(List<Item>* aList)
:_iterator(aList){}
//遍历操作
template<class Item>
bool ListTraverser<Item>::Traverse()
{
bool result = false;
for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())
{
result = ProcessItem(_iterator.CurrenItem());
if(result == false)
break;
}
return result;
}
//如果需要打印不同的链表,必须实现不同的迭代器,所以内部迭代器实现会比较麻烦。
class PrintNEmployees :
public ListTraverser<Employee*>
{
public:
PrintNEmployees(List<Employee*>* aList,
int n)
: ListTraverser<Employee*>(aList), _total(n), _count(){}
protected:
bool ProcessItem(Employee*
const&);
private:
int _total;
int _count;
}
bool PrintNEmployees::ProcessItem(Employee*
const& e)
{
_count++;
e->Print();
return _count < _total;
}
//这里就不需要自己实现遍历函数,直接调用内部迭代器的函数打印。
List<Employee*>* employees;
PrintNEmployees pa(employees,
);
pa.Traverse();
ListIterator<Employee*> i(employees);
//下面是外部迭代器的打印过程,必须自己实现逻辑
int count =
;
for(i.First(); !i.IsDone(); i.Next())
{
count++;
i.CurrenItem()->Print();
)
{
break;
}
}
//这个迭代器可以过滤一些元素,只有通过测试菜能打印出来
template<class Item>
class FilteringListTraverser
{
public:
FilteringListTraverser(List<Item>* aList);
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) =
;
virtual bool TestItem(const Item&) =
;
private:
ListIterator<Item> _iterator;
};
template<class Item>
void FilteringListTraverser<Item>::Traverse()
{
bool result = false;
for(_iterator.First(); !=_iterator.IsDone(); _iterator.Next())
{
//先测试
if(TestItem(_iterator.CurrenItem()))
{
result = ProcessItem(_iterator.CurrenItem());
if(result == false)
break;
}
}
return result;
}
设计模式 笔记 迭代器模式 Iterator的更多相关文章
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- 二十四种设计模式:迭代器模式(Iterator Pattern)
迭代器模式(Iterator Pattern) 介绍提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示. 示例有一个Message实体类,某聚合对象内的各个元素均为该实体对象,现 ...
- [设计模式] 16 迭代器模式 Iterator Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对迭代器模式是这样说的:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示. 类图和实例: 迭代器模式由以下角 ...
- 设计模式之迭代器模式(Iterator)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 学习笔记——迭代器模式Iterator
迭代器模式,使用很多,但是很少实现.常用的集合都支持迭代器. 集合中的CreateIterator()可用于创建自己的迭代器,在里面通过调用迭代器的构造函数Iterator(Aggregate)来绑定 ...
- 行为型设计模式之迭代器模式(Iterator)
结构 意图 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示. 适用性 访问一个聚合对象的内容而无需暴露它的内部表示. 支持对聚合对象的多种遍历. 为遍历不同的聚合结构提供一 ...
- 设计模式之迭代器模式 Iterator
代码实现 public interface MyIterator { void first(); //将游标指向第一个元素 void next(); //将游标指向下一个元素 boolean hasN ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
随机推荐
- 反射式DLL注入--方法
使用RWX权限打开目标进程,并为该DLL分配足够大的内存. 将DLL复制到分配的内存空间. 计算DLL中用于执行反射加载的导出的内存偏移量. 调用CreateRemoteThread(或类似的未公开的 ...
- visual studio 单元测试的认识
单元测试(unit testing),对软件中的最小单元进行检查和验证,其一般验证对象是一个函数或者一个类. Team Test 是 Visual Studio 集成的单元测试框架,它支持: 测试方法 ...
- oracle 11.2.0.1 rman异机恢复 11.2.0.3(windows X64)
问题原因: 误操作,需要时间点恢复. 备份情况:rman 备份,每天一次全备份,并且附带备份当天所有产生的archivelog,无expdp备份 恢复目标: 恢复到9号晚上21点数据 源系统:WIND ...
- 【转】Nginx学习---负载均衡的原理、分类、实现架构,以及使用场景
[原文]https://www.toutiao.com/i6593604356799463944/ [原文]https://www.toutiao.com/i6592741060194075143/ ...
- 团队-UML
UML设计 分工 刘双玉 李佳铭 杜宏庆 肖小强 汪志彬 江郑 符天愉 邓弘立 后台数据库 求购模块 浏览检索商品 即时聊天系统 商品管理 管理员系统 后台商品发布收藏系统 登录注册与个人信息系统 U ...
- css实现常用的两栏三栏布局
1.两栏 <div class="wrapper"> <div class="half left">left box <p> ...
- C++虚函数再复习
- Spring boot结合mybatis开发的报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found),经过排查确定是没有找到xml的原因 ...
- PAT B1042 字符统计 (20 分)
请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过 1000 的字符串.字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母, ...
- 包学会之浅入浅出 Vue.js:开学篇
2016年,乃至接下来整个2017年,如果你要问前端技术框架什么最火,那无疑就是前端三巨头:React.Angular.Vue.没错,什么jQuery,seaJs,gulp等都逐渐脱离了热点.面试的时 ...