《設(shè)計(jì)模式24》-訪問(wèn)者模式_第1頁(yè)
《設(shè)計(jì)模式24》-訪問(wèn)者模式_第2頁(yè)
《設(shè)計(jì)模式24》-訪問(wèn)者模式_第3頁(yè)
《設(shè)計(jì)模式24》-訪問(wèn)者模式_第4頁(yè)
《設(shè)計(jì)模式24》-訪問(wèn)者模式_第5頁(yè)
已閱讀5頁(yè),還剩18頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、7 訪問(wèn)者模式(Decorator Pattern)訪問(wèn)者模式解決:在訪問(wèn)者模式解決:在Food結(jié)構(gòu)穩(wěn)定的前提下,需要訪問(wèn)結(jié)構(gòu)穩(wěn)定的前提下,需要訪問(wèn)Food及其子類(lèi)及其子類(lèi)問(wèn)題-Animal:Eat的實(shí)現(xiàn)void Animal:Eat(Food* food) if (Meat * m = dynamic_cast(food)_!=NULL) /animal 吃吃 m m-MeatFunction(); else if (Bone * b= dynamic_cast(food)_!=NULL) ) /animal 吃吃 b b-BoneFunction(); 1. 使用了使用了if-else結(jié)構(gòu)

2、,多了不易處理結(jié)構(gòu),多了不易處理2. 使用了動(dòng)態(tài)類(lèi)型識(shí)別和向下類(lèi)型轉(zhuǎn)換,違背了里氏替換原則,不易擴(kuò)展使用了動(dòng)態(tài)類(lèi)型識(shí)別和向下類(lèi)型轉(zhuǎn)換,違背了里氏替換原則,不易擴(kuò)展3. 由于由于Meat和和Bone會(huì)有不同的外部接口,難以在會(huì)有不同的外部接口,難以在Eat中形成一致的行為中形成一致的行為解決問(wèn)題解決方法:將解決方法:將Eat行為的實(shí)現(xiàn),移到行為的實(shí)現(xiàn),移到Food及其子類(lèi)中,并在子類(lèi)中給出不及其子類(lèi)中,并在子類(lèi)中給出不同的實(shí)現(xiàn)。同的實(shí)現(xiàn)。問(wèn)題-解決全部問(wèn)題了嗎1.如果Animal也有子類(lèi),如Tiger和Dog類(lèi)呢2.如果Animal系列增加一個(gè)Cook(Food * )操作呢?增加子類(lèi)Tiger

3、和Dogvoid Meat:BeEaten(Animal * ani)if ( (Tiger * tiger = dynamic_cast(ani)!= NULL ) / meat 被被 tiger 吃吃 else if (Dog * dog = dynamic_cast(ani)!= NULL ) / meat 被被 dog 吃吃 1. 又回到了初始的問(wèn)題(動(dòng)態(tài)類(lèi)型識(shí)別和向下類(lèi)型轉(zhuǎn)換)!又回到了初始的問(wèn)題(動(dòng)態(tài)類(lèi)型識(shí)別和向下類(lèi)型轉(zhuǎn)換)!2. 增加新操作,如增加新操作,如Cook和和Store,F(xiàn)ood的接口必須改變的接口必須改變3. Food的子類(lèi)擴(kuò)展的子類(lèi)擴(kuò)展BeEaten和和BeCook

4、ed等的實(shí)現(xiàn),會(huì)造成子類(lèi)數(shù)量的激等的實(shí)現(xiàn),會(huì)造成子類(lèi)數(shù)量的激增增問(wèn)題的根源理想中的實(shí)現(xiàn):void Animal:Eat(Food* food) (this,food)-Eat();現(xiàn)實(shí)是殘酷的:現(xiàn)實(shí)是殘酷的:1. 我們常用的語(yǔ)言我們常用的語(yǔ)言C/C+,Java,C#,Objective C等都不支持動(dòng)態(tài)雙分派。等都不支持動(dòng)態(tài)雙分派。2. 有個(gè)別語(yǔ)言支持動(dòng)態(tài)雙分派有個(gè)別語(yǔ)言支持動(dòng)態(tài)雙分派單分派和多分派 決定執(zhí)行哪個(gè)具體行為過(guò)程,由消息名,接收決定執(zhí)行哪個(gè)具體行為過(guò)程,由消息名,接收對(duì)象,參數(shù)共同決定。對(duì)象,參數(shù)共同決定。v 除消息名之外,v 若由接收對(duì)象決定行為過(guò)程,稱(chēng)單分派;v 若由接收對(duì)象和

5、參數(shù)對(duì)象共同決定行為過(guò)程, 成多分派; 靜態(tài)多分派(重載為例) class Some public: virtual void Do(Base& d) cout Some:Do(Base&); virtual void Do(D1 & d1) cout Some: Do(D1&); virtual void Do(D2 & d2) cout Some: Do(D2&);;靜態(tài)多分派(重載為例)class SubSome1:public Some public: virtual void Do(Base& d) coutSumSome1:D

6、o(Base&); virtual void Do(D1 & d1) coutSumSome1: Do(D1&); virtual void Do(D2 & d2) coutSumSome1: Do(D2&);;class SubSome2:public Some public: virtual void Do(Base& d) coutSumSome2:Do(Base&); virtual void Do(D1 & d1) coutSumSome2: Do(D1&); virtual void Do(D2 & d

7、2) coutSumSome2: Do(D2&);;靜態(tài)多分派(重載為例)main() D1 d1; D2 d2; SubSome1 s1; SubSome2 s2; Some & obj = s2; obj.Do(d1); / 輸出為:輸出為: SubSome2:Do(d1&); obj.Do(d2); / 輸出為:輸出為: SubSome2:Do(d2&); Base & d = d1; obj.Do(d); / 輸出為:輸出為: SubSome2:Do(Base&);1.決定程序執(zhí)行哪個(gè)重載函數(shù),是在編譯時(shí)就確定的,而不是運(yùn)行時(shí)刻。決定程序

8、執(zhí)行哪個(gè)重載函數(shù),是在編譯時(shí)就確定的,而不是運(yùn)行時(shí)刻。2.在編譯時(shí),編譯器只能識(shí)別變量的靜態(tài)類(lèi)型,所以重載是靜態(tài)編聯(lián)的。在編譯時(shí),編譯器只能識(shí)別變量的靜態(tài)類(lèi)型,所以重載是靜態(tài)編聯(lián)的。3.例子說(shuō)明重載可以實(shí)現(xiàn)多分派,但屬于靜態(tài)多分派例子說(shuō)明重載可以實(shí)現(xiàn)多分派,但屬于靜態(tài)多分派動(dòng)態(tài)單分派class Horse public: virtual Horse() virtual void Name( ) cout馬馬;class WhiteHorse:public Horse public:virtual void Name( ) cout白馬白馬;class RedHorse:public Horse

9、public:virtual void Name( ) cout紅馬紅馬;main() WhiteHorse wh; RedHorse rh; Horse& h = wh; /輸出輸出 白馬白馬 coutVisit(this);void Bone:BeEaten(Visitor * v) v-Visit (this);void Meat:BeCooked(Visitor * v) v-Visit(this);void Bone:BeCooked(Visitor * v) v-Visit (this);現(xiàn)在現(xiàn)在Food中的各方法,其行為一中的各方法,其行為一致了。致了。同樣的行為,起一個(gè)

10、相同的名吧。同樣的行為,起一個(gè)相同的名吧。就叫就叫Accept。這樣這樣Food系列中的各種系列中的各種BeXXX都可以去掉了,合成一個(gè)都可以去掉了,合成一個(gè)Acceptvoid Food:Accept(Visitor& v) v.Visit(this); 步驟3/4/5-說(shuō)明v步驟2中,我們采用了重載的方式定義接口。 Visit(Meat * ) 和Visit(Bone *).v也可以采用非重載的方式定義接口,如接口為:VisitMeat(Meat*)和VisitBone(Bone*)v具體采用哪種方式定義接口,可按個(gè)人習(xí)慣v若采用非重載方式,那么子類(lèi)的Accept需Override

11、. void Meat:Accept(Visitor& v) v.VisitMeat(this); void Bone:Accept(Visitor& v) v.VisitBone(this); 步驟7 Animal中的實(shí)現(xiàn)Void Tiger:Eat( Meat * meat) Visitor * v= new TigerEatVisitor; meat-Accept(v);Void Tiger:Eat( Bone* bone) Visitor * v= new TigerEatVisitor; bone-Accept(v);Void Dog:Cook( Meat * mea

12、t) Visitor * v= new DogCookVisitor; meat-Accept(v);Void Dog:Cook( Bone* bone) Visitor * v= new DogCookVisitor; bone-Accept(v);藍(lán)色部分完全可改成:藍(lán)色部分完全可改成:Eat (Food * food)那么那么實(shí)例化不同的實(shí)例化不同的Visitor子類(lèi)子類(lèi)完成的就是相應(yīng)的實(shí)現(xiàn)。完成的就是相應(yīng)的實(shí)現(xiàn)。Eat(Food * food) Visitor * v= new TigerEatVisitor;Food-Accept(v);Cook(Food * food) Visit

13、or * v= new DogCookVisitor;Food-Accept(v);訪問(wèn)者模式效果vFood的子類(lèi)數(shù)量需要穩(wěn)定。否則會(huì)導(dǎo)致Visitor的接口變化v將對(duì)各子類(lèi)不相同接口的訪問(wèn),變?yōu)榻y(tǒng)一。v擴(kuò)展各種訪問(wèn)的實(shí)現(xiàn)容易。如從TigerXXXVisitor派生子類(lèi)擴(kuò)展即可。v增加新的訪問(wèn)容易。如增加Tiger的Store(Meat*)和Store(Bone *),只需從TigerVisitor派生新的子類(lèi)TigerStoreVisitor即可。訪問(wèn)者模式結(jié)構(gòu)例例子說(shuō)明v貨車(chē)、轎車(chē)、車(chē)組的屬性各不相同,成員函數(shù)也不相同,即接口難以統(tǒng)一v計(jì)算運(yùn)營(yíng)費(fèi)用時(shí),使用的算法、依據(jù)、原則等總會(huì)有變化v還

14、會(huì)增加計(jì)算保險(xiǎn)費(fèi)用,計(jì)算固定資產(chǎn)凈值等v(貨車(chē)、轎車(chē)、車(chē)組)結(jié)構(gòu)穩(wěn)定class Visitor public: virtual Visitor() virtual int 計(jì)算貨車(chē)計(jì)算貨車(chē) (貨車(chē)貨車(chē) * ) = 0; virtual int 計(jì)算轎車(chē)計(jì)算轎車(chē) (轎車(chē)轎車(chē) *) = 0; virtual int 計(jì)算車(chē)組計(jì)算車(chē)組 (車(chē)組車(chē)組 *) = 0;class 運(yùn)營(yíng)費(fèi)用運(yùn)營(yíng)費(fèi)用Visitor:public Visitor Public: virtual int 計(jì)算貨車(chē)計(jì)算貨車(chē) (貨車(chē)貨車(chē) * c) money += c-Get載重載重()*10; virtual int 計(jì)算轎車(chē)計(jì)算轎車(chē) (轎車(chē)轎車(chē) *c) money += c-Get車(chē)齡車(chē)齡( )*5; virtual int 計(jì)算車(chē)組計(jì)算車(chē)組 (車(chē)組車(chē)組 *c) money += c-GetTotalCount()*8; int GetMoney() const return money;Private:int money; ;void 貨車(chē)貨車(chē):Accept(Visitor& v) v.計(jì)算貨車(chē)計(jì)算貨車(chē)(this); void 轎車(chē)轎

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論