本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.csdn.net/lovelion/article/details/17517213
主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。
我应该理解和掌握的:
1)能够画出这个设计模式的架构框图;
2)能够根据架构框图写出对应的伪代码;
3)这个模式的应用场景,主要优缺点。
1.迭代器模式
迭代器是很常见的模式,他将聚合类中负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历的分离,无需暴露聚合类的内部类属性即可对其进行操作。我们常用聚合对象来存储一系列的数据,如vector,聚合对象拥有两个职责:一是存储数据,而是遍历数据。前者是聚合对象的基本职责,后者是可变化和分离的。将遍历数据的行为从聚合对象中分离出来,封装在一个被称为迭代器的对象中,由迭代器来提供遍历聚合类对象内部数据的行为。
(1)定义
迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部元素。
1)迭代器结构图
在迭代器结构图中包含聚合和迭代器两个层次结构,考虑到系统的灵活性和可扩展性,在迭代器中应用了工厂方法模式。
2)参与者
a) Iterator(抽象迭代器):定义访问和遍历元素的借口;
b) ConcreteIterator(具体迭代器):具体迭代器实现迭代器的接口,对该聚合遍历时跟踪当前位置;
c) Aggregate(聚合):存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂的角色。
d) ConcreteAggregate(具体聚合类):创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。
3)看图写代码
/*
** FileName : IteratorPattern
** Author : lin005
** Date : 2015/02/08
** Description : More information, please go to http://blog.csdn.net/amd123456789
*/
//define a node
typedef struct Node_s
{
int value;
Node_s* next;
}Node;
class p_List; //提前申明
//Abstract Iterator
class _Iterator
{
public:
virtual ~_Iterator(){};
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsLast() = 0;
virtual Node* getCurrentNode() = 0;
};
//抽象迭代器的子类
class ConcreteIterator : public _Iterator
{
public:
ConcreteIterator(p_List* l):list(l){}
~ConcreteIterator();
virtual void First(); //第一个元素
virtual void Next(); //当前元素的下一个元素
virtual bool IsLast(); //是否最后一个元素
virtual Node* getCurrentNode(); //获取当前迭代器所指向的元素
private:
p_List* list; //包含链表
Node* pc; //当前元素
};
//链表
class p_List
{
public:
p_List(){phead = NULL; ptail = NULL; count = 0;}
~p_List()
{
removeAll();
if(iter)
{
delete iter;
iter = NULL;
}
}
//获取元素个数
int getCount()
{
return count;
}
//获取指定元素
Node* get(const int a)const
{
Node* p = phead;
while(p)
{
if(p->value == a)
{
return p;
}
p = p->next;
}
return NULL;
}
//获取第一个元素
Node* First()const
{
return phead;
}
//获取最后一个元素
Node* Last()const
{
return ptail;
}
//是否包含指定元素
bool IsInclude(const int a)const
{
Node* p = phead;
while(p)
{
if(p->value == a)
{
return true;
}
p = p->next;
}
return false;
}
//添加一个指定元素
void add(const int a)
{
Node *pnew = new Node;
pnew->next = NULL;
pnew->value = a;
if(phead == NULL)
{
phead = pnew;
ptail = pnew;
count++;
}
else
{
ptail->next = pnew;
ptail = pnew;
}
}
//删除一个元素
void remove(Node* p)
{
if(phead == NULL)
return;
if(phead == p)
{
if(phead->next == NULL)
{
ptail = NULL;
}
phead = p->next;
delete p;
p = NULL;
}
else
{
Node* pt = phead;
while(pt)
{
if(pt->next == p)
{
//if(p->next == NULL)
{
// pt->next = NULL;
}
// else
{
pt->next = pt->next->next;
}
delete p;
p = NULL;
break;
}
pt = pt->next;
}
}
}
//删除所有元素
void removeAll()
{
while(phead)
{
Node* p = phead;
phead = p->next;
delete p;
p = NULL;
}
ptail = NULL;
}
//是否第一个元素
bool isFirst(Node* p)
{
if(p == phead)
return true;
return false;
}
//链表是否为空
bool isEmpty()
{
return count == 0;
}
//生成一个迭代器
_Iterator* createdIter()
{
iter = new ConcreteIterator(this);
return iter;
}
private:
Node* phead; //第一个节点
Node* ptail; //最后一个节点
int count; //元素个数
_Iterator* iter; //迭代器
};
void ConcreteIterator::First()
{
pc = list->First();
}
void ConcreteIterator::Next()
{
if(list->First())
{
pc = pc->next;
}
else
{
pc = NULL;
}
}
bool ConcreteIterator::IsLast()
{
return pc == list->Last()->next;
}
Node* ConcreteIterator::getCurrentNode()
{
return pc;
}
ConcreteIterator::~ConcreteIterator()
{
}
//客户端测试
#define SAFE_DELETE(p) if(p){delete p; p = NULL;}
int main(int argc, const char * argv[]) {
p_List* l = new p_List();
l->add(20);
l->add(30);
l->add(40);
_Iterator* iter = new ConcreteIterator(l);//有客户端主动生成迭代器,需要手动delete
_Iterator* iter1 = l->createdIter(); //直接用链表自己生成
//客户端生成迭代器测试
for(iter->First(); !iter->IsLast();iter->Next())
{
cout<<iter->getCurrentNode()->value<<endl;
}
//链表生成的迭代器
for(iter1->First(); !iter1->IsLast(); iter1->Next())
{
if(iter1->getCurrentNode()->value == 20)
{
l->remove(iter1->getCurrentNode());
}
}
//链表生成迭代器测试
for(iter1->First(); !iter1->IsLast();iter1->Next())
{
cout<<iter1->getCurrentNode()->value<<endl;
}
SAFE_DELETE(l);
SAFE_DELETE(iter);
return 0;
}
(2)总结
1)优点
a) 支持不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。仅需用一个不同的迭代器的实例替代原先的实例即可
b) 迭代器简化了聚合类的接口。
c) 在同一个聚合器上可以有多个遍历。每个迭代器保持他自己的遍历状态,因此可以同时进行多个遍历。
d) 在迭代器中引入抽象层,增加新的聚合类和迭代器很方便,无需修改原有代码,符合开闭原则。
2)缺点
a) 迭代器分离了数据存储和遍历数据的职责,增加新的聚合类需要增加对应的迭代器类,类的个数成对增加,一定程度上增加的系统的复杂性。
b) 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展。
(3)适用场景
1) 访问一个聚合对象而无需暴露它的内部表示。
2) 支持对聚合对象的多种遍历。
3) 为遍历不同的聚合结构提供一个统一的接口。