| 網(wǎng)站首頁 | 關(guān)于我們 | 開發(fā)優(yōu)勢(shì) | 產(chǎn)品展示 |
| 合作企業(yè) | 新聞動(dòng)態(tài) | 聯(lián)系我們 | 電話聯(lián)系 |
文章作者:濟(jì)南軟件開發(fā) 時(shí)間:2016年11月08日
View Code
再回頭看看,自己寫的代碼都有點(diǎn)不認(rèn)識(shí)了。是的,那個(gè)時(shí)候,就是直接將鏈表的創(chuàng)建和遍歷都放在一類中,就是為了方便,直到那天看了迭代器設(shè)計(jì)模式,讓我有了一次回過頭來重新審視自己寫過的代碼,認(rèn)識(shí)自己的不足的機(jī)會(huì)。
迭代器模式
在GOF的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對(duì)迭代器模式是這樣說的:提供一種方法順序訪問一個(gè)聚合對(duì)象中各個(gè)元素,而又不需要暴露該對(duì)象的內(nèi)部表示。
一個(gè)聚合對(duì)象,就是所謂的對(duì)象容器了;作為一個(gè)容器,都應(yīng)該提供一種方法來讓別人可以訪問它的元素;但是,有的時(shí)候,我是不希望遍歷容器的人知道我的容器是如何實(shí)現(xiàn)的;那該怎么辦?就像我在大學(xué)那樣實(shí)現(xiàn)的鏈表,只提供了從頭到尾的遍歷,如果我需要從尾到頭的遍歷呢?是不是我又要添加對(duì)應(yīng)的方法了呢!??!容器的遍歷方式千變?nèi)f化,我們不知道需求是如何的,如果需求變了,那么我們的代碼就會(huì)發(fā)生很大的改動(dòng),所以,我們需要去改變;對(duì)于上面的代碼,當(dāng)我對(duì)同一個(gè)鏈表對(duì)象進(jìn)行多次遍歷時(shí),是不是就出現(xiàn)了m_pCurrent對(duì)象混亂的局面呢?是的,這一切的一切,都說明,我們必須去將一個(gè)容器的內(nèi)部結(jié)構(gòu)與它的遍歷進(jìn)行解耦,要是出現(xiàn)上面的情況時(shí),我們就無法面對(duì)。就好比STL中的容器,它將容器中對(duì)象的實(shí)現(xiàn)和遍歷很好的解耦了,所以,我們就無法知道它的內(nèi)部是如何組織對(duì)象數(shù)據(jù)的,同時(shí),我們也可以按照我們自己的想法去遍歷容器,而不會(huì)出現(xiàn)任何差錯(cuò)。在我們的項(xiàng)目中使用迭代器模式就能很好的將容器對(duì)象的內(nèi)部表示與對(duì)它的遍歷進(jìn)行解耦。接下來,我們?cè)賮碓敿?xì)的總結(jié)迭代器模式。
UML類圖
Iterator:定義迭代器訪問和遍歷元素的接口;
ConcreteIterator:實(shí)現(xiàn)具體的迭代器;
Aggregate:定義的容器,創(chuàng)建相應(yīng)迭代器對(duì)象的接口;
ConcreteAggregate:具體的容器實(shí)現(xiàn)創(chuàng)建相應(yīng)迭代器的接口,該操作返回ConcreteIterator的一個(gè)適當(dāng)?shù)膶?shí)例。
使用場(chǎng)合
訪問一個(gè)聚合對(duì)象的內(nèi)容而無需暴露它的內(nèi)部表示;
支持對(duì)聚合對(duì)象的多種遍歷(從前到后,從后到前);
為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口,即支持多態(tài)迭代。
作用
它支持以不同的方式遍歷一個(gè)聚合,甚至都可以自己定義迭代器的子類以支持新的遍歷;
迭代器簡化了聚合的接口,有了迭代器的遍歷接口,聚合本身就不再需要類似的遍歷接口了。這樣就簡化了聚合的接口;
在同一個(gè)聚合上可以有多個(gè)遍歷,每個(gè)迭代器保持它自己的遍歷狀態(tài);因此,我們可以同時(shí)進(jìn)行多個(gè)遍歷。
代碼實(shí)現(xiàn)
View Code
代碼中實(shí)現(xiàn)了一個(gè)單向鏈表,將鏈表與迭代器解耦。對(duì)于多態(tài)迭代,添加抽象類AbstractJTList,聲明如下:
View Code
類JTList繼承該抽象類,并實(shí)現(xiàn)GetIterator,如下:
View Code
好了,這樣的話,在客戶端就不用去new JTListIterator了,只需要這樣:
1 Iterator *pIterator = pJTList->GetIterator();
這就完全好了;但是,這樣又出現(xiàn)另外一個(gè)問題,我在GetIterator中new了一個(gè)JTListIterator,對(duì)于客戶端來說,我并不知道這個(gè)new操作的存在,就會(huì)出現(xiàn)客戶端不會(huì)去釋放這個(gè)new開辟的內(nèi)存,那么如何實(shí)現(xiàn)這個(gè)內(nèi)存的自動(dòng)釋放呢。好了,就結(jié)合迭代器模式,再將之前總結(jié)的RAII機(jī)制再實(shí)際運(yùn)用一次。
根據(jù)RAII機(jī)制,需要將這個(gè)迭代器進(jìn)行封裝,讓它具有自動(dòng)釋放的功能,就得借助另一個(gè)類,如下:
復(fù)制代碼
1 class IteratorPtr
2 {
3 public:
4 IteratorPtr(Iterator *pIterator) : m_pIterator(pIterator){}
5 ~IteratorPtr() { delete m_pIterator; }
6
7 Iterator *operator->(){ return m_pIterator; }
8 Iterator &operator*() { return *m_pIterator; }
9
10 private:
11 IteratorPtr(const IteratorPtr &);
12 IteratorPtr &operator=(const IteratorPtr &);
13 void *operator new(size_t size);
14 void operator delete(void *);
15
16 private:
17 Iterator *m_pIterator;
18 };
復(fù)制代碼
我們?cè)谑褂玫臅r(shí)候,就像下面這樣:
1 IteratorPtr pIterator(pJTList->GetIterator());
這樣就省去了釋放迭代器的麻煩了。這里一共涉及了三個(gè)DEMO工程,提供完整DEMO工程下載。(工程下載)
總結(jié)
迭代器模式是一個(gè)很經(jīng)典的模式。但是,就是因?yàn)樗?jīng)典了,如果每次都要程序員去重復(fù)造輪子,就有點(diǎn)說不過去了,所以,現(xiàn)在基本成型的類庫,都非常好的實(shí)現(xiàn)了迭代器模式,在使用這些類庫提供的容器時(shí),并不需要我們親自去實(shí)現(xiàn)對(duì)應(yīng)的迭代器;就好比STL了。但是話又說回來了,如此經(jīng)典的東西,你不去學(xué)習(xí)是不是很可惜??;是吧,在當(dāng)今社會(huì),技多不壓身。好了,永遠(yuǎn)記住,設(shè)計(jì)模式是一種思想,并不是一層不變的,一種思想,你懂的。
想要了解更多詳情歡迎來電咨詢18678812288
登陸網(wǎng)址:m.h6244.cn。
聯(lián)系人:王經(jīng)理。