Iterator 迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示,又称游标(Cursor)。该模式的应用应该十分熟悉了,C++ 标准库 STL 中不同的容器都提供了相同的迭代器接口。这一模式的关键思想是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中。迭代器类定义了一个访问列表元素的接口,迭代器对象负责跟踪当前的元素,即它知道哪些元素已经遍历过了。
Iterator 适用于:1.访问一个聚合对象的内容而无需暴露它的内部表示。2.支持对聚合对象的多种遍历。3.对遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)。
Iterator 的通用结构如下:
参与者
Iterator:迭代器定义访问和遍历元素的接口。
ConcreteIterator:具体迭代器实现迭代器接口。对该聚合遍历时跟踪当前位置。
Aggregate:聚合定义创建相应迭代器对象的接口。
ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回 ConcreteIterator 的一个适当的实例。
实现时应该注意:
1.谁控制迭代器,不由客户控制迭代时,称为外部迭代器(external iterator),而当由迭代器控制时,称为内部迭代器(internal iterator)。使用外部迭代器,客户必须主动推进遍历的步伐,显式地向迭代器请求下一个元素。相反,使用内部迭代器时,客户只需提交一个执行请求,而迭代器将对聚合中的每一个元素实施该操作。 外部迭代器比内部迭代器更灵活。
2.谁定义遍历算法,聚合本身可以定义遍历算法,并在遍历过程中用迭代器来存储当前迭代的状态,这种迭代器称为一个游标,因为它仅用来指示当前位置。如果由迭代器负责遍历算法,那么将易于在相同的聚合上使用不同的迭代算法,同时也易于在不同的聚合上重用相同的算法。但同时,将遍历算法放入迭代器中会破坏聚合的封装性。
3.迭代器的健壮性非常重要,一个健壮的迭代器(robust iterator)保证插入和删除操作不会干扰遍历,且不需拷贝该聚合。
4.在 C++ 中使用多态的迭代器,使用多态迭代器是有代价的。它们要求用一个 Factory Method 动态的分配迭代器对象。因此仅当必须多态时才使用它们,否则使用在栈中分配内存的具体的迭代器。多态迭代器有另一个缺点:客户必须负责删除它们。Proxy 为此提供了一种补救方法,我们可以使用一个栈分配的 Proxy 作为实际迭代器的中间代理。该代理在其析构器中删除该迭代器。这样当该代理生命周期结束时,实际迭代器将同它一起释放,即使在发生异常时,该代理机制能保证正确地清除迭代器对象,这就是著名的C++“资源分配即初始化”技术的一个应用。
5.空迭代器,一个空迭代器(NullIterator)是一个退化的迭代器,它有助于处理边界条件。一个 NullIterator 总是已经完成了遍历,即它的 IsDone 操作总是返回 true。等还有其它比较复杂的注意事项。
Iterator 迭代器模式示例代码如下:
下面的代码分别示例了:1.正向迭代器;2.反向迭代器;3.迭代器代理;4.内部迭代器;5内部迭代器,过滤器;
//Aggregate.h 容器类
1:
2: #pragma once
3:
4: template
5: class Iterator;
6:
7: // 聚集的抽象基类
8: template
9: class Aggregate
10: {
11: public:
12: virtual ~Aggregate(){ }
13:
14: //为避免限定于一种特定的聚集实现迭代器, 实现多态
15: //Aggregate 定义一个 Factory Method
16: //各聚集子类重定义这个方法以返回相应的迭代器
17: virtual Iterator * CreateIterator() = 0; //默认创建正向迭代器
18:
19: //正向迭代器和反向迭代器, 只为示例,实际并不这样实现
20: virtual Iterator * CreateForwardIterator() //正向迭代器
21: {
22: return 0;
23: }
24: virtual Iterator * CreateReverseIterator() //反向迭代器
25: {
26: return 0;
27: }
28: virtual int GetSize() const = 0;
29: virtual T GetItem(int nIndex) const = 0;
30: protected:
31: Aggregate(){ }
32: };
33:
34: // 一个具体的聚集类,定义相应迭代器对象的接口,这里是用数组表示
35: // 具体聚集实现创建相应迭代器的接口,并返回具体迭代器的实例
36: template
37: class ConcreteAggregate : public Aggregate
38: {
39: public:
40: ConcreteAggregate(int nSize)
41: : m_nSize(nSize), m_pData(NULL)
42: {
43: m_pData = new T[m_nSize];
44:
45: for (int i = 0; i < nSize; ++i)
46: {
47: m_pData[i] = i;
48: }
49: }
50: virtual ~ConcreteAggregate()
51: {
52: delete [] m_pData;
53: m_pData = NULL;
54: std::cout << "~ConcreteAggregate()" << std::endl;
55: }
56: //默认创建一个正向迭代器
57: Iterator
* CreateIterator()
58: {
59: return new ForwardIterator ( this);
60: }
61: Iterator
* CreateForwardIterator()
62: {
63: return new ForwardIterator ( this);
64: }
65: //创建一个反向迭代器
66: Iterator
* CreateReverseIterator()
67: {
68: return new ReverseIterator ( this);
69: }
70: virtual int GetSize() const
71: {
72: return m_nSize;
73: }
74: virtual T GetItem(int nIndex) const
75: {
76: if (nIndex < m_nSize)
77: {
78: return m_pData[nIndex];
79: }
80: else
81: {
82: return -1;
83: }
84: }
85: private:
86: int m_nSize;
87: T *m_pData;
88: };
//Iterator.h 不同的迭代器类
1:
2: #pragma once
3: #include
4:
5: template
6: class Aggregate;
7:
8: // 迭代器的抽象基类
9: template
10: class Iterator
11: {
12: public:
13: virtual ~Iterator(){}
14:
15: //定义访问和遍历元素的接口
16: //First, Next, IsDone, CurrentItem
17: virtual void First() = 0; //将迭代器指向聚集第一个元素
18: virtual void Next() = 0; //将迭代器指向当前的下一个元素
19: virtual bool IsDone() const = 0; //是否已经遍历完毕
20: virtual T CurrentItem() const = 0; //返回聚集当前元素
21: protected:
22: Iterator(){ };
23: };
24:
25: //1. 针对具体聚集的迭代器类, 正向迭代器
26: // 访问 ConcreateAggregate 容器类的迭代器类
27: // 实现迭代器接口,对聚合遍历时跟踪当前位置
28: template
29: class ForwardIterator : public Iterator
30: {
31: public:
32: ForwardIterator(Aggregate
* pAggregate)
33: : m_pConcreteAggregate(pAggregate), m_nIndex(0)
34: { }
35: virtual ~ForwardIterator(){
36: m_pConcreteAggregate = NULL;
37: std::cout << "~ForwardIterator()" << std::endl;
38: }
39:
40: //First, Next, IsDone, CurrentItem
41: virtual void First(){ m_nIndex = 0; }
42: virtual void Next(){ ++m_nIndex; }
43: virtual bool IsDone() const
44: {
45: return m_nIndex == m_pConcreteAggregate->GetSize();
46: }
47: virtual T CurrentItem() const
48: {
49: return m_pConcreteAggregate->GetItem(m_nIndex);
50: }
51: private:
52: Aggregate
*m_pConcreteAggregate;
53: int m_nIndex;
54: };
55:
56: //2. 具体的迭代器, 反向迭代器
57: template
58: class ReverseIterator : public Iterator
59: {
60: public:
61: ReverseIterator(Aggregate
* pAggregate)
62: : m_pConcreteAggregate(pAggregate)
63: {
64: m_nIndex = m_pConcreteAggregate->GetSize() - 1;
65: }
66: virtual ~ReverseIterator(){
67: m_pConcreteAggregate = NULL;
68: std::cout << "~ReverseIterator()" << std::endl;
69: }
70: //First, Next, IsDone, CurrentItem
71: void First()
72: {
73: m_nIndex = m_pConcreteAggregate->GetSize() - 1;
74: }
75: void Next(){ m_nIndex--; }
76: bool IsDone() const { return m_nIndex < 0; }
77: T CurrentItem() const
78: {
79: return m_pConcreteAggregate->GetItem(m_nIndex);
80: }
81: private:
82: Aggregate
*m_pConcreteAggregate;
83: int m_nIndex;
84: };
85:
86: //3. 迭代器代理
87: /*
88: *注意 CreateIterator 返回的是一个动态分配的迭代器对象.在使用完之后,
89: *必须删除这个迭代器,否则会造成内存泄漏.
90: *为方便客户,我们提供一个 IeratorPtr 作为迭代器的代理, 这个机制可以
91: *保证在 Iterator对象离开作用域时清除它. IteratorPtr 总是在栈上分配
92: *(只需定义私有的 new 和 delete 操作符, 不需要附加实现).
93: *IteratorPtr 重载了操作符 -> 和 *,使得可将 IteratorPtr 用作一个指向
94: *迭代器的指针.IteratorPtr 的成员都实现为内联的,不会产生任何额外开销.
95: */
96: template
97: class IteratorPtr
98: {
99: public:
100: IteratorPtr(Iterator
* i): _i(i){ }
101: ~IteratorPtr()
102: {
103: delete _i;
104: std::cout << "~IteratorPtr()" << std::endl;
105: }
106:
107: Iterator * operator->(){ return _i; }
108: Iterator & operator*() { return *_i; }
109: private:
110: //disallow copy and assignment to avoid multiple deletion of _i
111: IteratorPtr(const IteratorPtr&);
112: IteratorPtr& operator=(const IteratorPtr&);
113: private:
114: Iterator
* _i;
115: };
116: //IteratorPtr 简化了打印代码: 假设有一个指向 Employee* 的雇员列表
117: //Aggregate * employees;
118: //IteratorPtr iterator(employee->CreateIterator());
119: //PrintEmployees(*iterator);
120: //*/
121:
122: //
123: //4. 内部迭代器示例
124: //一个内部的或被动的 ListIterator 类
125: //此时由迭代器来控制迭代,并对列表中的每一个元素施行同一个操作
126: /*
127: ListTraverser 以一个 Aggregate 实例为参数,在内部,它使用一个外部
128: ForwardIterator 进行遍历. Traverse 启动遍历并对每一元素项调用
129: ProcessItem 操作. 内部迭代器可在某次 ProcessItem 操作返回 false
130: 时提前终止本次遍历.而Traverse返回一个布尔值指示本次遍历是否提前终止.
131: */
132: template
133: class AggregateTraverser
134: {
135: public:
136: AggregateTraverser(Aggregate
* aggregate)
137: :_iterator(aggregate){ }
138: virtual bool Traverse()
139: {
140: bool result = false;
141: for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())
142: {
143: result = ProcessItem(_iterator.CurrentItem());
144: if(result == false)
145: {
146: break;
147: }
148: }
149: std::cout << std::endl;
150: return result;
151: }
152: protected:
153: virtual bool ProcessItem(const T& e) = 0;
154: private:
155: ForwardIterator
_iterator;
156: };
157:
158: //内部迭代器的实现要比外部迭代器复杂
159: //为使用一个 AggregateTraverser 来打印具体的聚集列表,必须定义
160: //一个AggregateTraverser 的子类并重定义其 ProcessItem 操作
161: //这里定义一个打印 Aggregate 列表的子类示例
162: class PrintIntTraverser : public AggregateTraverser<int>
163: {
164: public:
165: PrintIntTraverser(Aggregate<int>* aggre, int n)
166: : AggregateTraverser<int>(aggre),_total(n),_count(0)
167: { }
168: protected:
169: bool ProcessItem(const int& e)
170: {
171: _count++;
172: std::cout << e << " ";
173: return _count < _total;
174: }
175: private:
176: int _total;
177: int _count;
178: };
179: //打印: 这里客户不需要如何进行迭代循环,整个迭代器可以重用
180: //这是内部迭代器的主要优点,其实现要比外部迭代器复杂一些
181: //List * employees;
182: //PrintIntTraverser pa(employees, employees->GetSize());
183: //pa.Traverse();
184:
185:
186: //5. 内部迭代器2
187: //内部迭代器可以封装不同类型的迭代, 例如, FilteringListTraverser
188: //封装的迭代仅处理能通过测试的那些列表元素:
189: template<class T>
190: class FilteringAggregateTraverser
191: {
192: public:
193: FilteringAggregateTraverser(Aggregate
* aggre)
194: :_iterator(aggre){ }
195:
196: //这个类接口除了增加了用于测试的成员函数 TestItem 外与
197: //AggregateTraverser 相同,它的子类将重定义 TestItem 以指定所需的测试.
198: bool Traverse()
199: {
200: bool result = false;
201: for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())
202: {
203: if(TestItem(_iterator.CurrentItem()))
204: {
205: result = ProcessItem(_iterator.CurrentItem());
206: if(result == false)
207: break;
208: }
209: }
210: return result;
211: }
212: protected:
213: virtual bool ProcessItem(const T&) = 0;
214: virtual bool TestItem(const T&) = 0;
215: private:
216: ForwardIterator
_iterator;
217: };
218:
219: //这里定义一个遍历 Aggregate 子类, 过滤元素小于 2 的元素
220: class Upper2Traverser : public FilteringAggregateTraverser<int>
221: {
222: public:
223: Upper2Traverser(Aggregate<int>* aggre, int n)
224: : FilteringAggregateTraverser<int>(aggre),_total(n),_count(0)
225: { }
226: protected:
227: bool ProcessItem(const int& e)
228: {
229: _count++;
230: std::cout << e << " ";
231: return _count < _total;
232: }
233: virtual bool TestItem(const int& e)
234: {
235: return e > 2 ;
236: }
237: private:
238: int _total;
239: int _count;
240: };
241: //*/
//test.cpp
1:
2: #include "Iterator.h"
3: #include "aggregate.h"
4: #include
5:
6: template
7: void PrintAggregate(Iterator & i)
8: {
9: for(i.First(); !i.IsDone(); i.Next())
10: {
11: std::cout << i.CurrentItem() << " ";
12: }
13: std::cout << std::endl;
14: }
15:
16: int main()
17: {
18: Aggregate<int>* pAggregate = new ConcreteAggregate<int>(10);
19:
20: //正向迭代器
21: Iterator<int>* pIterator = pAggregate->CreateForwardIterator();
22: std::cout << "Now, the ForwardIterator: " << std::endl;
23: PrintAggregate(*pIterator);
24: //或者自己操作迭代器,如下
25: for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
26: {
27: std::cout << pIterator->CurrentItem() << " ";
28: }
29: std::cout << std::endl;
30: //*/
31:
32: //反向迭代器
33: std::cout << "Now, the ReverseIterator: " << std::endl;
34: Iterator<int>* pReverseIter = pAggregate->CreateReverseIterator();
35: PrintAggregate(*pReverseIter);
36:
37: //迭代器代理
38: { //加上 { }, 演示迭代器代理的功能
39: IteratorPtr<int> iterPtr(pAggregate->CreateForwardIterator());
40: std::cout << "Now, the IteratorPtr: " << std::endl;
41: PrintAggregate(*iterPtr);
42: }//IterPtr 作用域至此结束
43: std::cout << "--------IteratorPtr 在离开作用域, 自动删除了真正的迭代器------"
44: << std::endl << std::endl;
45:
46: //内部迭代器
47: std::cout << "Now, the Inner Iterator: " << std::endl;
48: PrintIntTraverser pt(pAggregate, pAggregate->GetSize());
49: pt.Traverse();
50: std::cout << std::endl;
51:
52: //内部迭代器2, 过滤器示例
53: std::cout << "Now, the Filter Iterator: " << std::endl;
54: Upper2Traverser upt(pAggregate, pAggregate->GetSize());
55: upt.Traverse();
56: std::cout << std::endl << std::endl;
57:
58:
59: delete pIterator;
60: delete pReverseIter;
61: delete pAggregate;
62:
63: return EXIT_SUCCESS;
64: }