“设计模式”学习之四:组合(结构型)与迭代器(行为型)
2011-08-07 23:21
761 查看
一、组合(Composite)
1、引言
看看树形结构,一些结点是叶结点(没有子结点),另一些可能还有子结点。组合模式用于构造这种基本对象和组合对象的“部分-整体”层次结构。其中,基本对象可以被组合成组合对象,而组合对象可以被递归组合成更复杂的组合对象。而对于基本对象和组合对象,用户可以一致使用。
2、一般思路
下图中,Leaf类中的int _numLeaf; 成员变量是为了区分实例化第几个基本对象(功能详见下节代码实例)。
Composite类中的vector <Component *>_comVector;用以存贮子部件,也可用Array、List、树、hash表等数据结构。
Composite::Operation()中将引入迭代器,用以遍历子部件。而Add/Remove/GetChild()都是为了管理子部件。
3、典型代码
依据上图类关系,编写简单实例完整代码如下:
代码运行情况如下:
4、应用提示
(1)共享组件可以节约存贮,享元Flyweight模式可以奏效。
(2)Composite可以用多种数据结构存贮子部件。当然,也可以应用解释器Interpreter模式,使用变量对应各节点,从而不用使用通用数据结构。
(3)组合经常和装饰者一块用,此时,装饰父类也必须声明Add/Remove/GetChild操作。
(4)组合模式是用“单一责任”设计原则来获取透明性——客户对叶节点与组合一视同仁,这样会损失部分操作“安全性”,比如需要警惕叶节点不能执行Add。
二、迭代器(Iterator,别名“游标”Cursor)
1、引言
对于一个聚合对象(如List、vector、自定义的组合类等等),如果想遍历其内部各个元素,又不暴露其内部结构,抑或需要不同的方式遍历它,甚至可能需要同时进行多个遍历。可以将对它的遍历访问功能抽离出来,封装到迭代器中。
2、一般思路
图中给出了迭代器Iterator的最小接口:First、Next、IsDone、CurrentItem四个。
Aggregate类即是需要迭代遍历的聚合类。
3、典型代码
////////////////////////////////////////////////
////////////////////////////////////////////////
输出情况如下图:若无“aIterator->First();”,则输出为“2 3 4”。(从第三个聚合对象开始)
4、应用提示
(1)如果需要针对不同的聚合对象动态创建不同的迭代器,需要Factory Method模式。
(2)迭代器常常在其内部存储一个备忘录Memento用以捕获一个迭代状态。
(3)在C++标准模板库STL中,迭代器是容器container
(包括:向量vector、双端队列deque、表list、队列queue、堆栈stack、集合set、多重集合multiset、映射map、多重映射multimap)和算法(有大约100个实现算法的模版函数,功能涉及比较、交换、查找、遍历、复制、修改、移除、反转、排序、合并等等)的黏合剂。
(4)空迭代器NullIterator用于处理边界条件,它总是表明已经完成了遍历,通过IsDone()中返回true,或者hasNext()返回false。
附:STL学习资料
关于STL的介绍:点击打开链接
百度百科:点击打开链接
《Effective STL》Scott Meyers著,50条有效使用STL的经验。
《STL源码剖析》侯捷著,挖掘STL内部机理。
1、引言
看看树形结构,一些结点是叶结点(没有子结点),另一些可能还有子结点。组合模式用于构造这种基本对象和组合对象的“部分-整体”层次结构。其中,基本对象可以被组合成组合对象,而组合对象可以被递归组合成更复杂的组合对象。而对于基本对象和组合对象,用户可以一致使用。
2、一般思路
下图中,Leaf类中的int _numLeaf; 成员变量是为了区分实例化第几个基本对象(功能详见下节代码实例)。
Composite类中的vector <Component *>_comVector;用以存贮子部件,也可用Array、List、树、hash表等数据结构。
Composite::Operation()中将引入迭代器,用以遍历子部件。而Add/Remove/GetChild()都是为了管理子部件。
3、典型代码
依据上图类关系,编写简单实例完整代码如下:
// composite.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <vector> #include <iostream> #include <conio.h> using namespace std; class Component { public: Component(){} virtual ~Component(){} virtual void Operation() = 0;//遍历子部件 virtual void Add(Component*){}//管理子部件 virtual void Remove(Component*){}//管理 virtual Component* GetChild(int index){return 0;}//获取某个子部件 }; class Leaf : public Component { public: Leaf(int numLeaf){_numLeaf = numLeaf;} ~Leaf(){} void Operation(){cout<< "Leaf "<<_numLeaf<<" operation..."<<endl;} int _numLeaf;//为了区分是第几个基本对象 }; class Composite : public Component { public: vector <Component *>_comVector;//以存贮子部件,也可用Array、List、树、hash表等数据结构 Composite(){} ~Composite(){} Component* GetChild(int index){return _comVector[index];} void Operation() { //引入迭代器实现按顺序访问子部件 vector <Component *>:: iterator _comIterator = _comVector.begin(); for (; _comIterator != _comVector.end(); _comIterator++) { (*_comIterator) -> Operation(); } } void Add(Component* com) { _comVector.push_back(com); } void Remove(Component* com) { // _comVector.erase(&com); } }; int _tmain(int argc, _TCHAR* argv[]) { Leaf * aLeaf0 = new Leaf(0); Leaf * aLeaf1 = new Leaf(1); Composite *aComposite = new Composite(); aComposite->Add(aLeaf0); aComposite->Add(aLeaf1); aComposite->Operation();//内部实现遍历 cout<<endl; Component *aComponent = aComposite->GetChild(0); aComponent->Operation(); aComponent = aComposite->GetChild(1); aComponent->Operation(); _getch();/*等待按键继续*/ return 0; }
代码运行情况如下:
4、应用提示
(1)共享组件可以节约存贮,享元Flyweight模式可以奏效。
(2)Composite可以用多种数据结构存贮子部件。当然,也可以应用解释器Interpreter模式,使用变量对应各节点,从而不用使用通用数据结构。
(3)组合经常和装饰者一块用,此时,装饰父类也必须声明Add/Remove/GetChild操作。
(4)组合模式是用“单一责任”设计原则来获取透明性——客户对叶节点与组合一视同仁,这样会损失部分操作“安全性”,比如需要警惕叶节点不能执行Add。
二、迭代器(Iterator,别名“游标”Cursor)
1、引言
对于一个聚合对象(如List、vector、自定义的组合类等等),如果想遍历其内部各个元素,又不暴露其内部结构,抑或需要不同的方式遍历它,甚至可能需要同时进行多个遍历。可以将对它的遍历访问功能抽离出来,封装到迭代器中。
2、一般思路
图中给出了迭代器Iterator的最小接口:First、Next、IsDone、CurrentItem四个。
Aggregate类即是需要迭代遍历的聚合类。
3、典型代码
////////////////////////////////////////////////
// "Iterator.h" // #ifndef _ITERATOR_H_ #define _ITERATOR_H_ typedef int Object; class Iterator; class Aggregate { public: Aggregate(){} virtual ~Aggregate(){} virtual Iterator* CreateIterator() = 0; virtual Object GetItem(int)=0; virtual int GetSize()=0; }; class ConcreteAggregate : public Aggregate { const static int SIZE = 5; Object _object[SIZE]; public: ConcreteAggregate() { for(int i=0; i<SIZE; i++) _object[i] = i; } ~ConcreteAggregate(){} Iterator* CreateIterator(); Object GetItem(int index) { if(index < this->GetSize()) return _object[index]; else return -1; } int GetSize(){return SIZE;} }; class Iterator { public: Iterator(){} virtual ~Iterator(){} virtual void First() = 0; virtual void Next() = 0; virtual bool IsDone() = 0; virtual Object CurrentItem() = 0; }; class ConcreteIterator : public Iterator { public: Aggregate * _aggregate; int _index; ConcreteIterator(Aggregate *aggregate, int index=2) { //假设默然从第三个聚合对象开始索引 this->_aggregate = aggregate; this->_index = index; } virtual ~ConcreteIterator(){} void First() { _index = 0; } void Next() { if(_index < _aggregate->GetSize()) _index++; } bool IsDone() { return (_index == _aggregate->GetSize()); } Object CurrentItem() { return _aggregate->GetItem(_index); } }; #endif //~_ITERATOR_H_
////////////////////////////////////////////////
// Iterator.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <conio.h> #include "Iterator.h" using namespace std; Iterator* ConcreteAggregate::CreateIterator() { return new ConcreteIterator(this); } int _tmain(int argc, _TCHAR* argv[]) { Aggregate * aAggregate = new ConcreteAggregate(); // Iterator *aIterator = new ConcreteIterator(aAggregate); Iterator *aIterator = aAggregate->CreateIterator();//工厂方法 aIterator->First();//从第一个聚合对象开始索引 for(; !aIterator->IsDone(); aIterator->Next()) cout<<aIterator->CurrentItem()<<endl; _getch();/*等待按键继续*/ return 0; }
输出情况如下图:若无“aIterator->First();”,则输出为“2 3 4”。(从第三个聚合对象开始)
4、应用提示
(1)如果需要针对不同的聚合对象动态创建不同的迭代器,需要Factory Method模式。
(2)迭代器常常在其内部存储一个备忘录Memento用以捕获一个迭代状态。
(3)在C++标准模板库STL中,迭代器是容器container
(包括:向量vector、双端队列deque、表list、队列queue、堆栈stack、集合set、多重集合multiset、映射map、多重映射multimap)和算法(有大约100个实现算法的模版函数,功能涉及比较、交换、查找、遍历、复制、修改、移除、反转、排序、合并等等)的黏合剂。
(4)空迭代器NullIterator用于处理边界条件,它总是表明已经完成了遍历,通过IsDone()中返回true,或者hasNext()返回false。
附:STL学习资料
关于STL的介绍:点击打开链接
百度百科:点击打开链接
《Effective STL》Scott Meyers著,50条有效使用STL的经验。
《STL源码剖析》侯捷著,挖掘STL内部机理。
相关文章推荐
- 【设计模式学习笔记九】【结构型模式】【组合模式(Composite)】
- C#面向对象设计模式学习笔记(8) - Composite 组合模式(结构型模式)
- 设计模式学习(结构型模式)—组合模式(Composite)
- 设计模式学习之组合模式(Composite,结构型模式)(10)
- 设计模式深入学习---Component组合模式(结构型模式)
- 步步为营 .NET 设计模式学习笔记 十五、Composite(组合模式)
- 设计模式9——结构型模式之组合模式
- java设计模式(结构型)之组合模式
- 设计模式16---设计模式之组合模式(Composite)(行为型)
- 设计模式学习(四):结构型模式
- 设计模式学习之外观模式(Facade,结构型模式)(8)
- 设计模式学习(五):行为型模式
- GoF23种设计模式之结构型模式之组合模式
- 设计模式 - 结构型模式 - 组合模式
- 设计模式学习总结6 - 行为型1 - ChainOfResponsibility责任链模式
- 设计模式学习总结7 - 行为型2 - Command命令模式
- 设计模式(8)-结构型-组合模式(Composite)
- 设计模式学习(十八)————组合模式
- 重学设计模式 - Composite(组合)模式 - 结构型
- 设计模式学习--组合模式