意图
提供一种方法顺序访问一个聚合对象中各个元素 , 而又不需暴露该对象的内部表示。
动机
一个聚合对象, 如列表(list), 应该提供一种方法来让别人可以访问它的元素,而又不需暴露它的内部结构
迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟踪当前的元素 ;即, 它知道哪些元素已经遍历过了。
适用性
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 支持对聚合对象的多种遍历。
- 为遍历不同的聚合结构提供一个统一的接口 (即, 支持多态迭代)。
结构
定义一个抽象列表类AbstractList,它提供操作列表的公共接口。类似地,我们也需要一个抽象的迭代器类Iterator,它定义公共的迭代接口。然后我们可以为每个不同的列表实现定义具体的Iterator子类。这样迭代机制就与具体的聚合类无关了。
参与者
Iterator:迭代器定义访问和遍历元素的接口。
ConcreteIterator:具体迭代器实现迭代器接口;对该聚合遍历时跟踪当前位置。
Aggregate:聚合定义创建相应迭代器对象的接口。
ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回ConcreteAggregate的一个适当的实例。
效果
- 访问一个聚合对象的内容而无需暴露它的内部表示;
- 支持对聚合对象的多种遍历(从前到后,从后到前);
- 为遍历不同的聚合结构提供一个统一的接口,即支持多态迭代。
实现
1 #include <iostream> 2 using namespace std; 3 4 typedef struct tagNode 5 { 6 int value; 7 tagNode *pNext; 8 }Node; 9 10 class JTList 11 { 12 public: 13 JTList() : m_pHead(NULL), m_pTail(NULL){}; 14 JTList(const JTList &); 15 ~JTList(); 16 JTList &operator=(const JTList &); 17 18 long GetCount() const; 19 Node *Get(const long index) const; 20 Node *First() const; 21 Node *Last() const; 22 bool Includes(const int &) const; 23 24 void Append(const int &); 25 void Remove(Node *pNode); 26 void RemoveAll(); 27 28 private: 29 Node *m_pHead; 30 Node *m_pTail; 31 long m_lCount; 32 }; 33 34 class Iterator 35 { 36 public: 37 virtual void First() = 0; 38 virtual void Next() = 0; 39 virtual bool IsDone() const = 0; 40 virtual Node *CurrentItem() const = 0; 41 }; 42 43 class JTListIterator : public Iterator 44 { 45 public: 46 JTListIterator(JTList *pList) : m_pJTList(pList), m_pCurrent(NULL){} 47 48 virtual void First(); 49 virtual void Next(); 50 virtual bool IsDone() const; 51 virtual Node *CurrentItem() const; 52 53 private: 54 JTList *m_pJTList; 55 Node *m_pCurrent; 56 }; 57 58 JTList::~JTList() 59 { 60 Node *pCurrent = m_pHead; 61 Node *pNextNode = NULL; 62 while (pCurrent) 63 { 64 pNextNode = pCurrent->pNext; 65 delete pCurrent; 66 pCurrent = pNextNode; 67 } 68 } 69 70 long JTList::GetCount()const 71 { 72 return m_lCount; 73 } 74 75 Node *JTList::Get(const long index) const 76 { 77 // The min index is 0, max index is count - 1 78 if (index > m_lCount - 1 || index < 0) 79 { 80 return NULL; 81 } 82 83 int iPosTemp = 0; 84 Node *pNodeTemp = m_pHead; 85 while (pNodeTemp) 86 { 87 if (index == iPosTemp++) 88 { 89 return pNodeTemp; 90 } 91 pNodeTemp = pNodeTemp->pNext; 92 } 93 return NULL; 94 } 95 96 Node *JTList::First() const 97 { 98 return m_pHead; 99 } 100 101 Node *JTList::Last() const 102 { 103 return m_pTail; 104 } 105 106 bool JTList::Includes(const int &value) const 107 { 108 Node *pNodeTemp = m_pHead; 109 while (pNodeTemp) 110 { 111 if (value == pNodeTemp->value) 112 { 113 return true; 114 } 115 pNodeTemp = pNodeTemp->pNext; 116 } 117 return false; 118 } 119 120 void JTList::Append(const int &value) 121 { 122 // Create the new node 123 Node *pInsertNode = new Node; 124 pInsertNode->value = value; 125 pInsertNode->pNext = NULL; 126 127 // This list is empty 128 if (m_pHead == NULL) 129 { 130 m_pHead = m_pTail = pInsertNode; 131 } 132 else 133 { 134 m_pTail->pNext = pInsertNode; 135 m_pTail = pInsertNode; 136 } 137 ++m_lCount; 138 } 139 140 void JTList::Remove(Node *pNode) 141 { 142 if (pNode == NULL || m_pHead == NULL || m_pTail == NULL) 143 { 144 return; 145 } 146 147 if (pNode == m_pHead) // If the deleting node is head node 148 { 149 Node *pNewHead = m_pHead->pNext; 150 m_pHead = pNewHead; 151 } 152 else 153 { 154 // To get the deleting node's previous node 155 Node *pPreviousNode = NULL; 156 Node *pCurrentNode = m_pHead; 157 while (pCurrentNode) 158 { 159 pPreviousNode = pCurrentNode; 160 pCurrentNode = pCurrentNode->pNext; 161 if (pCurrentNode == pNode) 162 { 163 break; 164 } 165 } 166 167 // To get the deleting node's next node 168 Node *pNextNode = pNode->pNext; 169 170 // If pNextNode is NULL, it means the deleting node is the tail node, we should change the m_pTail pointer 171 if (pNextNode == NULL) 172 { 173 m_pTail = pPreviousNode; 174 } 175 176 // Relink the list 177 pPreviousNode->pNext = pNextNode; 178 } 179 180 // Delete the node 181 delete pNode; 182 pNode = NULL; 183 --m_lCount; 184 } 185 186 void JTList::RemoveAll() 187 { 188 delete this; 189 } 190 191 void JTListIterator::First() 192 { 193 m_pCurrent = m_pJTList->First(); 194 } 195 196 void JTListIterator::Next() 197 { 198 m_pCurrent = m_pCurrent->pNext; 199 } 200 201 bool JTListIterator::IsDone() const 202 { 203 return m_pCurrent == m_pJTList->Last()->pNext; 204 } 205 206 Node *JTListIterator::CurrentItem() const 207 { 208 return m_pCurrent; 209 } 210 211 int main() 212 { 213 JTList *pJTList = new JTList; 214 pJTList->Append(10); 215 pJTList->Append(20); 216 pJTList->Append(30); 217 pJTList->Append(40); 218 pJTList->Append(50); 219 pJTList->Append(60); 220 pJTList->Append(70); 221 pJTList->Append(80); 222 pJTList->Append(90); 223 pJTList->Append(100); 224 225 Iterator *pIterator = new JTListIterator(pJTList); 226 227 // Print the list by JTListIterator 228 for (pIterator->First(); !pIterator->IsDone(); pIterator->Next()) 229 { 230 cout << pIterator->CurrentItem()->value << "->"; 231 } 232 cout << "NULL" << endl; 233 234 // Test for removing 235 Node *pDeleteNode = NULL; 236 for (pIterator->First(); !pIterator->IsDone(); pIterator->Next()) 237 { 238 pDeleteNode = pIterator->CurrentItem(); 239 if (pDeleteNode->value == 100) 240 { 241 pJTList->Remove(pDeleteNode); 242 break; 243 } 244 } 245 246 // Print the list by JTListIterator 247 for (pIterator->First(); !pIterator->IsDone(); pIterator->Next()) 248 { 249 cout << pIterator->CurrentItem()->value << "->"; 250 } 251 cout << "NULL" << endl; 252 253 delete pIterator; 254 delete pJTList; 255 256 return 0; 257 }