亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++設計模式之迭代器模式

2020-01-26 15:16:13
字體:
來源:轉載
供稿:網友

前言

又到年底了,時間真的過的好快啊。最近也非常感傷,總是懷念大學的日子,做夢的時候也常常夢到。夢到大學在電腦前傻傻的敲著鍵盤,寫著代碼,對付著數據結構與算法的作業;建立一個鏈表,遍歷鏈表,打印鏈表?,F在把那個時候聲明的鏈表的頭文件拿出來看看:

復制代碼 代碼如下:

typedef struct tagNode
{
     int value;
     tagNode *pPre;
     tagNode *pNext;
}Node;
 
class CList
{
public:
     CList();
     CList(size_t n);
     ~CList();
 
     bool PushBack(int value);
     bool PopBack(int &value);
     bool Insert(int pos, int value);
     bool Delete(int pos);
     bool IsEmpty();
     int GetLength();
 
     void Print();
 
     // To iterate the list
     bool HasNext();
     int Next();
 
private:
     int m_iLength;
     Node *m_pCurrent;
     Node *m_pHead;
     Node *m_pTail;
};

再回頭看看,自己寫的代碼都有點不認識了。是的,那個時候,就是直接將鏈表的創建和遍歷都放在一類中,就是為了方便,直到那天看了迭代器設計模式,讓我有了一次回過頭來重新審視自己寫過的代碼,認識自己的不足的機會。

迭代器模式

在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對迭代器模式是這樣說的:提供一種方法順序訪問一個聚合對象中各個元素,而又不需要暴露該對象的內部表示。

一個聚合對象,就是所謂的對象容器了;作為一個容器,都應該提供一種方法來讓別人可以訪問它的元素;但是,有的時候,我是不希望遍歷容器的人知道我的容器是如何實現的;那該怎么辦?就像我在大學那樣實現的鏈表,只提供了從頭到尾的遍歷,如果我需要從尾到頭的遍歷呢?是不是我又要添加對應的方法了呢?。?!容器的遍歷方式千變萬化,我們不知道需求是如何的,如果需求變了,那么我們的代碼就會發生很大的改動,所以,我們需要去改變;對于上面的代碼,當我對同一個鏈表對象進行多次遍歷時,是不是就出現了m_pCurrent對象混亂的局面呢?是的,這一切的一切,都說明,我們必須去將一個容器的內部結構與它的遍歷進行解耦,要是出現上面的情況時,我們就無法面對。就好比STL中的容器,它將容器中對象的實現和遍歷很好的解耦了,所以,我們就無法知道它的內部是如何組織對象數據的,同時,我們也可以按照我們自己的想法去遍歷容器,而不會出現任何差錯。在我們的項目中使用迭代器模式就能很好的將容器對象的內部表示與對它的遍歷進行解耦。接下來,我們再來詳細的總結迭代器模式。

UML類圖

Iterator:定義迭代器訪問和遍歷元素的接口;
ConcreteIterator:實現具體的迭代器;
Aggregate:定義的容器,創建相應迭代器對象的接口;
ConcreteAggregate:具體的容器實現創建相應迭代器的接口,該操作返回ConcreteIterator的一個適當的實例。

使用場合

1.訪問一個聚合對象的內容而無需暴露它的內部表示;
2.支持對聚合對象的多種遍歷(從前到后,從后到前);
3.為遍歷不同的聚合結構提供一個統一的接口,即支持多態迭代。

作用

1.它支持以不同的方式遍歷一個聚合,甚至都可以自己定義迭代器的子類以支持新的遍歷;
2.迭代器簡化了聚合的接口,有了迭代器的遍歷接口,聚合本身就不再需要類似的遍歷接口了。這樣就簡化了聚合的接口;
3.在同一個聚合上可以有多個遍歷,每個迭代器保持它自己的遍歷狀態;因此,我們可以同時進行多個遍歷。

代碼實現

復制代碼 代碼如下:

#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;
};
 
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;
};
 
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;
}
 
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;
}

代碼中實現了一個單向鏈表,將鏈表與迭代器解耦。對于多態迭代,添加抽象類AbstractJTList,聲明如下:

復制代碼 代碼如下:

class AbstractJTList
{
public:
     virtual Iterator *GetIterator() const = 0;
};

類JTList繼承該抽象類,并實現GetIterator,如下:

復制代碼 代碼如下:

Iterator *JTList::GetIterator() const
{
     return new JTListIterator(this);
}

好了,這樣的話,在客戶端就不用去new JTListIterator了,只需要這樣:

復制代碼 代碼如下:

Iterator *pIterator = pJTList->GetIterator();

這就完全好了;但是,這樣又出現另外一個問題,我在GetIterator中new了一個JTListIterator,對于客戶端來說,我并不知道這個new操作的存在,就會出現客戶端不會去釋放這個new開辟的內存,那么如何實現這個內存的自動釋放呢。好了,就結合迭代器模式,再將之前總結的RAII機制再實際運用一次。
根據RAII機制,需要將這個迭代器進行封裝,讓它具有自動釋放的功能,就得借助另一個類,如下:

復制代碼 代碼如下:

class IteratorPtr
{
public:
     IteratorPtr(Iterator *pIterator) : m_pIterator(pIterator){}
     ~IteratorPtr() { delete m_pIterator; }
 
     Iterator *operator->(){ return m_pIterator; }
     Iterator &operator*() { return *m_pIterator; }
 
private:
     IteratorPtr(const IteratorPtr &);
     IteratorPtr &operator=(const IteratorPtr &);
     void *operator new(size_t size);
     void operator delete(void *);
 
private:
     Iterator *m_pIterator;
};

我們在使用的時候,就像下面這樣:

復制代碼 代碼如下:

IteratorPtr pIterator(pJTList->GetIterator());

這樣就省去了釋放迭代器的麻煩了。這里一共涉及了三個DEMO工程,提供完整DEMO工程下載。(工程下載

總結

迭代器模式是一個很經典的模式。但是,就是因為它太經典了,如果每次都要程序員去重復造輪子,就有點說不過去了,所以,現在基本成型的類庫,都非常好的實現了迭代器模式,在使用這些類庫提供的容器時,并不需要我們親自去實現對應的迭代器;就好比STL了。但是話又說回來了,如此經典的東西,你不去學習是不是很可惜??;是吧,在當今社會,技多不壓身。好了,永遠記住,設計模式是一種思想,并不是一層不變的,一種思想,你懂的。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品户外野外| 国产日韩精品入口| 国产精品对白刺激| 92看片淫黄大片欧美看国产片| 国产精品欧美在线| 日韩欧美国产网站| 成人精品一区二区三区| 亚洲国产中文字幕久久网| 亚洲欧美日韩天堂| 日韩久久精品电影| 伊人青青综合网站| 日韩亚洲欧美成人| 国产精品极品在线| 视频一区视频二区国产精品| 国产精品96久久久久久| 91精品视频专区| 国产精品高清在线观看| 欧美成人在线免费视频| 亚洲电影av在线| 91精品国产91久久久久| 狠狠色狠色综合曰曰| 欧美—级高清免费播放| 国产网站欧美日韩免费精品在线观看| 成人黄色av播放免费| 欧美激情亚洲一区| 国产欧美日韩高清| 精品国产区一区二区三区在线观看| 1769国产精品| 91亚洲国产成人精品性色| 亚洲va国产va天堂va久久| 精品国产户外野外| 国产一区二区免费| 77777亚洲午夜久久多人| 中文字幕精品视频| 欧美日韩人人澡狠狠躁视频| 亚洲自拍偷拍视频| 欧美日韩在线第一页| 不卡av电影在线观看| 亚洲一区二区三区久久| 亚洲激情中文字幕| 国产成人午夜视频网址| 国产香蕉精品视频一区二区三区| 欧美高清不卡在线| 97视频在线观看亚洲| 国模精品视频一区二区三区| 精品国产自在精品国产浪潮| 久久久亚洲网站| 亚洲欧美三级在线| 国产一区二区色| 在线成人免费网站| 57pao国产成人免费| 亚洲91av视频| 国产精品久久国产精品99gif| 日韩av网站大全| 国产丝袜精品第一页| 国产欧美最新羞羞视频在线观看| 日韩欧美亚洲范冰冰与中字| 久久久久亚洲精品成人网小说| 91精品视频大全| 久久久久久999| 亲子乱一区二区三区电影| 精品中文视频在线| 久久精品91久久香蕉加勒比| 欧美影院久久久| 午夜精品一区二区三区在线视频| 91高清视频在线免费观看| 亚洲成人久久久久| 欧美富婆性猛交| 欧美放荡办公室videos4k| 亚洲最新av在线网站| 欧美日韩成人在线播放| 中文字幕少妇一区二区三区| 色偷偷av一区二区三区乱| 一色桃子一区二区| 精品久久在线播放| 亚洲sss综合天堂久久| 日本精品久久中文字幕佐佐木| 欧洲成人午夜免费大片| 久久久精品在线观看| 国产一区二区三区精品久久久| 欧美视频第一页| 欧美激情视频一区二区三区不卡| 久久国产精品偷| 欧美刺激性大交免费视频| 亚洲福利视频二区| 国产精品高清网站| 午夜精品久久久久久久99热浪潮| 亚洲第一精品福利| 欧美大尺度在线观看| 欧美亚洲另类制服自拍| 久久在线免费观看视频| 国产精品扒开腿做爽爽爽男男| 久久久之久亚州精品露出| 日本欧美一级片| 国产亚洲精品va在线观看| 热久久免费国产视频| 亚洲最大福利视频网| 欧美激情亚洲视频| 日韩欧美中文字幕在线观看| 日韩电视剧免费观看网站| 日韩大片免费观看视频播放| 国产亚洲精品久久久| 国产日本欧美在线观看| 国产精品私拍pans大尺度在线| 亚洲一区亚洲二区亚洲三区| 成人国产精品日本在线| 色妞色视频一区二区三区四区| 国自产精品手机在线观看视频| 自拍偷拍亚洲在线| 亚洲成人在线视频播放| 国产成人一区二区三区| 一级做a爰片久久毛片美女图片| 日韩大胆人体377p| 中文字幕亚洲天堂| 欧美资源在线观看| 一本色道久久综合狠狠躁篇的优点| 亚洲欧美精品中文字幕在线| 欧美日本亚洲视频| 精品人伦一区二区三区蜜桃免费| 日韩毛片在线观看| 成人激情av在线| 欧美综合一区第一页| 俺也去精品视频在线观看| 2019av中文字幕| 亚洲毛茸茸少妇高潮呻吟| 亚洲人成网在线播放| 亚洲精品视频播放| 欧美刺激性大交免费视频| 欧美日本啪啪无遮挡网站| 亚洲国产成人爱av在线播放| 啊v视频在线一区二区三区| 日韩综合中文字幕| 992tv成人免费影院| 亚洲男人第一网站| 性夜试看影院91社区| 成人在线免费观看视视频| 亚洲一区二区三区在线视频| 亚洲人成电影网站色www| 精品在线小视频| 亚洲一区二区三区成人在线视频精品| 精品日本高清在线播放| 亚洲韩国欧洲国产日产av| 日韩欧美福利视频| 日韩电影免费观看在线观看| 国产精品久久久| 亚洲国产精品yw在线观看| 亚洲第一区第一页| 91精品美女在线| 欧洲一区二区视频| 精品一区二区电影| 精品动漫一区二区三区| 欧美一级在线播放| 一本一本久久a久久精品牛牛影视| 日韩成人在线视频| 精品成人69xx.xyz| 精品国产91久久久| 国产午夜精品全部视频在线播放| 亚州欧美日韩中文视频| 不卡av在线播放| 欧洲成人午夜免费大片| 国产成人综合久久| 日韩中文字幕在线播放| 亚洲国产成人爱av在线播放| 国产成人黄色av|