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: }