设计模式之 - 迭代器模式

来源:互联网 发布:开淘宝需要什么 编辑:程序博客网 时间:2024/05/01 18:10

一、定义

        迭代器( Iterator)模式,又叫做游标( Cursor)模式。 GOF 给出的定义为:提供一种方法访问一个容器( container)对象中各个元素,而又不需暴露该对象的内部细节。

        从定义可见,迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。而迭代器模式的出现,很好的解决了上面两种情况的弊端。

二、结构

        先来看下迭代器模式的真面目吧:

1) 迭代器角色( Iterator):迭代器角色负责定义访问和遍历元素的接口。

2) 具体迭代器角色( ConcreteIterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。

3) 容器角色( Container):容器角色负责提供创建具体迭代器角色的接口。

4) 具体容器角色( Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

三、实现

#include <iostream>using namespace std;//容器角色typedef struct tagNode{     int value;     tagNode *pNext;}Node;//具体容器(用链表代替)class JTList{public:     JTList() : m_pHead(NULL), m_pTail(NULL){};     JTList(const JTList &);     ~JTList();     JTList &operator=(const JTList &);     long GetCount() const;     Node *Get(const long index) const;     Node *First() const;     Node *Last() const;     bool Includes(const int &) const;     void Append(const int &);     void Remove(Node *pNode);     void RemoveAll();private:     Node *m_pHead;     Node *m_pTail;     long m_lCount;};//迭代器角色class Iterator{public:     virtual void First() = 0;     virtual void Next() = 0;     virtual bool IsDone() const = 0;     virtual Node *CurrentItem() const  = 0;};JTList::~JTList(){     Node *pCurrent = m_pHead;     Node *pNextNode = NULL;     while (pCurrent)     {          pNextNode = pCurrent->pNext;          delete pCurrent;          pCurrent = pNextNode;     }}long JTList::GetCount()const{     return m_lCount;}Node *JTList::Get(const long index) const{     // The min index is 0, max index is count - 1     if (index > m_lCount - 1 || index < 0)     {          return NULL;     }     int iPosTemp = 0;     Node *pNodeTemp = m_pHead;     while (pNodeTemp)     {          if (index == iPosTemp++)          {               return pNodeTemp;          }          pNodeTemp = pNodeTemp->pNext;     }     return NULL;}Node *JTList::First() const{     return m_pHead;}Node *JTList::Last() const{     return m_pTail;}bool JTList::Includes(const int &value) const{     Node *pNodeTemp = m_pHead;     while (pNodeTemp)     {          if (value == pNodeTemp->value)          {               return true;          }          pNodeTemp = pNodeTemp->pNext;     }     return false;}void JTList::Append(const int &value){     // Create the new node     Node *pInsertNode = new Node;     pInsertNode->value = value;     pInsertNode->pNext = NULL;     // This list is empty     if (m_pHead == NULL)     {          m_pHead = m_pTail = pInsertNode;     }     else     {          m_pTail->pNext = pInsertNode;          m_pTail = pInsertNode;     }     ++m_lCount;}void JTList::Remove(Node *pNode){     if (pNode == NULL || m_pHead == NULL || m_pTail == NULL)     {          return;     }     if (pNode == m_pHead) // If the deleting node is head node     {          Node *pNewHead = m_pHead->pNext;          m_pHead = pNewHead;     }     else     {          // To get the deleting node's previous node          Node *pPreviousNode = NULL;          Node *pCurrentNode = m_pHead;          while (pCurrentNode)          {               pPreviousNode = pCurrentNode;               pCurrentNode = pCurrentNode->pNext;               if (pCurrentNode == pNode)               {                    break;               }          }          // To get the deleting node's next node          Node *pNextNode = pNode->pNext;          // If pNextNode is NULL, it means the deleting node is the tail node, we should change the m_pTail pointer          if (pNextNode == NULL)          {               m_pTail = pPreviousNode;          }          // Relink the list          pPreviousNode->pNext = pNextNode;     }     // Delete the node     delete pNode;     pNode = NULL;     --m_lCount;}void JTList::RemoveAll(){     delete this;}//具体迭代器角色class JTListIterator : public Iterator{public:     JTListIterator(JTList *pList) : m_pJTList(pList), m_pCurrent(NULL){}     virtual void First();     virtual void Next();     virtual bool IsDone() const;     virtual Node *CurrentItem() const;private:     JTList *m_pJTList;     Node *m_pCurrent;};void JTListIterator::First(){     m_pCurrent = m_pJTList->First();}void JTListIterator::Next(){     m_pCurrent = m_pCurrent->pNext;}bool JTListIterator::IsDone() const{     return m_pCurrent == m_pJTList->Last()->pNext;}Node *JTListIterator::CurrentItem() const{     return m_pCurrent;}int main(){     JTList *pJTList = new JTList;     pJTList->Append(10);     pJTList->Append(20);     pJTList->Append(30);     pJTList->Append(40);     pJTList->Append(50);     pJTList->Append(60);     pJTList->Append(70);     pJTList->Append(80);     pJTList->Append(90);     pJTList->Append(100);     Iterator *pIterator = new JTListIterator(pJTList);     // Print the list by JTListIterator     for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())     {          cout<<pIterator->CurrentItem()->value<<"->";     }     cout<<"NULL"<<endl;     // Test for removing     Node *pDeleteNode = NULL;     for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())     {          pDeleteNode = pIterator->CurrentItem();          if (pDeleteNode->value == 100)          {               pJTList->Remove(pDeleteNode);               break;          }     }     // Print the list by JTListIterator     for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())     {          cout<<pIterator->CurrentItem()->value<<"->";     }     cout<<"NULL"<<endl;     delete pIterator;     delete pJTList;     return 0;}

四、 适用情况

        由上面的讲述,我们可以看出迭代器模式给容器的应用带来以下好处:
1) 支持以不同的方式遍历一个容器角色。根据实现方式的不同,效果上会有差别。
2) 简化了容器的接口。
3) 对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。
        由此也能得出迭代器模式的适用范围:
1) 访问一个容器对象的内容而无需暴露它的内部表示。
2) 支持对容器对象的多种遍历。
3) 为遍历不同的容器结构提供一个统一的接口(多态迭代)。

0 0