摘要:感受設(shè)計(jì)演變過(guò)程中所蘊(yùn)含的大智慧,體會(huì)樂(lè)與怒的程序人生中值得回味的一幕幕。本文轉(zhuǎn)自大話設(shè)計(jì)模式第七章之代理模式!
本文轉(zhuǎn)載于: http://blog.csdn.net/monkey_d_meng/article/details/5689877
7.1為別人做嫁衣
“小菜,今天見(jiàn)這個(gè)叫嬌嬌的美女見(jiàn)得如何呀?”大鳥(niǎo)一回家來(lái)就問(wèn)小菜。
“唉,別提了,人家是有男朋友的。”小菜無(wú)精打采地答道。
“有男朋友了啊,這倒是我沒(méi)料到,那為什么還找你幫忙修電腦?”
“她男友叫戴勵(lì),在北京讀大學(xué)呢,他們高中就開(kāi)始談戀愛(ài)了。”小菜說(shuō),“而且她還告訴了我一件比較有趣的事。”
“哦,是什么?”
“是這樣的,我們?cè)诔燥埖臅r(shí)候,我就問(wèn)她,怎么不找男友幫修電腦。她說(shuō)男友在北京讀書(shū),所以沒(méi)辦法幫助修。我心里一想,‘你在上海怎么男友會(huì)在北京’,正想問(wèn)他們是怎么認(rèn)識(shí)的,她卻接著問(wèn)我想不想知道他男友追她的事。哈,這不正是我所希望的嗎,于是我就跟著她開(kāi)始了美好的回憶。”
“又不是你談戀愛(ài),說(shuō)得這么肉麻,還‘美好的回憶’。她回憶什么了?”
“當(dāng)時(shí)她是這么說(shuō)的:‘那是在我高中二年級(jí)時(shí)的一天下午……’”
“嬌嬌同學(xué),這是有人送你的禮物。”一個(gè)男生手拿著一個(gè)芭比娃娃送到她的面前。
“戴勵(lì)同學(xué).這是什么意思?”嬌嬌望著同班的這個(gè)男生,感覺(jué)很奇怪。
“是這樣的,我的好朋友,隔壁三班的卓賈易同學(xué),請(qǐng)我代他送你這個(gè)禮物的。”戴勵(lì)有些臉紅。
“為什么要送我禮物,我不認(rèn)識(shí)他呀。”
“他說(shuō)……他說(shuō)……他說(shuō)想和你交個(gè)朋友。”戴勵(lì)臉更紅了,右手抓后腦勺,說(shuō)話吞吞吐吐。
“不用這樣,我不需要禮物的。”嬌嬌顯然想拒絕,
“別別別,他是我最好的朋友,他請(qǐng)我代他送禮物給你,也是下了很大決心的,你看在我之前時(shí)常幫你輔導(dǎo)數(shù)學(xué)習(xí)題的面子上,就接受一下吧。”戴勵(lì)有些著急。
“那好吧,今天我對(duì)解析幾何的橢圓那里還是不太憧,你再給我講講。”嬌嬌提出條件后接過(guò)禮物。
“沒(méi)問(wèn)題,我們到教室去講吧。”戴勵(lì)松了口氣。
幾天后
“嬌嬌,這是卓賈易送你的花。”
“嬌嬌,這是卓賈易送你的巧克力。”
“我不要他送的東西了,我也不想和他交朋友。我愿意……我愿意和你做朋友!”嬌嬌終于忍不住了,
直接表白。
“啊,……我不是在做夢(mèng)吧……”戴勵(lì)喜從天降,不敢相信。
“呆子!”嬌嬌微笑地罵道。
戴勵(lì)用手抓了抓頭發(fā)說(shuō),“其實(shí)我也喜歡你。不過(guò),……不過(guò),那我該如何向卓賈易交待昵?”
從此戴勵(lì)和嬌嬌開(kāi)始戀愛(ài)了。畢業(yè)后,戴勵(lì)考上了北京XX大學(xué),而嬌嬌讀了上海的大專(zhuān)。
“喂,醒醒,還在陶醉呀。這個(gè)戴勵(lì)根本就是一個(gè)大騙子,哪有什么卓賈易,這是他自己想泡MM找的借口。”大鳥(niǎo)不屑一顧。
“我當(dāng)時(shí)也是這么想的,但她說(shuō)是真的有這個(gè)人,后來(lái)那個(gè)卓賈易氣死了,差點(diǎn)和戴勵(lì)翻臉。”小菜肯定地說(shuō)。
“那就不能怪戴勵(lì)了,卓賈易就是為別人在做嫁衣,所以自己苦惱也是活該,誰(shuí)叫他不自己主動(dòng),找人代理談戀愛(ài),神經(jīng)病呀,”
“是呀,都怪他自己。為別人做嫁衣的滋味不好受哦。”
“這里又可以談到一個(gè)設(shè)計(jì)模式了。”
“你不說(shuō)我也知道是哪一個(gè),代理模式對(duì)吧?”
“哈,說(shuō)得沒(méi)錯(cuò)。小菜真是越來(lái)越聰明。”
“去去去,口是心非的東西,代理模式又是怎么講的?”
“你先試著寫(xiě)如果卓賈易直接追嬌嬌,應(yīng)該如何做?”
7.2沒(méi)有代理的代碼
十分鐘后,小菜寫(xiě)出了第一份代碼。
結(jié)構(gòu)圖
- //被追求者類(lèi)?? ??
- public ? class ?SchoolGirl????
- {????
- ???? public ?String???name;????
- ????
- ???? public ?String?getName()????
- ????{????
- ???????? return ? this .name;????
- ????}????
- ????
- ???? public ? void ?setName(String?name)????
- ????{????
- ???????? this .name?=?name;????
- ????}????
- }????
- //追求者類(lèi)?? ??
- public ? class ?Pursuit????
- {????
- ????SchoolGirl??mm;????
- ????
- ???? public ?Pursuit(SchoolGirl?mm)????
- ????{????
- ???????? this .mm?=?mm;????
- ????}????
- ????
- ???? public ? void ?giveDolls()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你洋娃娃" );????
- ????}????
- ????
- ???? public ? void ?giveFlowers()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你鮮花" );????
- ????}????
- ????
- ???? public ? void ?giveChocolate()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你巧克力" );????
- ????}????
- }????
- //客戶端代碼?? ??
- public ? class ?Main????
- {????
- ???? public ? static ? void ?main(String[]?args)????
- ????{????
- ????????SchoolGirl?jiaojiao?=? new ?SchoolGirl();????
- ????????jiaojiao.setName( "李嬌嬌" );????
- ????
- ????????Pursuit?zhuojiayi?=? new ?Pursuit(jiaojiao);????
- ????
- ????????zhuojiayi.giveDolls();????
- ????????zhuojiayi.giveFlowers();????
- ????????zhuojiayi.giveChocolate();????
- ????}????
- }????
?
“我了個(gè)擦,嬌嬌并不認(rèn)識(shí)卓賈易,這樣寫(xiě)的話不就等于卓賈易自己去送東西了嘛。”
“是哇,這如何處理來(lái)著?”
“而且,你丫把戴勵(lì)給弄哪去了?”
“哈,對(duì)的對(duì)的,戴勵(lì)就是代理啊。”
7.3只有代理的代碼
十分鐘后。
結(jié)構(gòu)圖
?
- //被追求者類(lèi)?? ??
- public ? class ?SchoolGirl????
- {????
- ???? public ?String???name;????
- ????
- ???? public ?String?getName()????
- ????{????
- ???????? return ? this .name;????
- ????}????
- ????
- ???? public ? void ?setName(String?name)????
- ????{????
- ???????? this .name?=?name;????
- ????}????
- }????
- //代理類(lèi)?? ??
- public ? class ?Proxy????
- {????
- ????SchoolGirl??mm;????
- ????
- ???? public ?Proxy(SchoolGirl?mm)????
- ????{????
- ???????? this .mm?=?mm;????
- ????}????
- ????
- ???? public ? void ?giveDolls()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你洋娃娃" );????
- ????}????
- ????
- ???? public ? void ?giveFlowers()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你鮮花" );????
- ????}????
- ????
- ???? public ? void ?giveChocolate()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你巧克力" );????
- ????}????
- }????
- //客戶端代碼?? ??
- public ? class ?Main????
- {????
- ???? public ? static ? void ?main(String[]?args)????
- ????{????
- ????????SchoolGirl?jiaojiao?=? new ?SchoolGirl();????
- ????????jiaojiao.setName( "李嬌嬌" );????
- ????
- ????????Proxy?daili?=? new ?Proxy(jiaojiao);????
- ????
- ????????daili.giveDolls();????
- ????????daili.giveFlowers();????
- ????????daili.giveChocolate();????
- ????}????
- }????
“我了個(gè)擦,你丫寫(xiě)的是個(gè)啥?”
“這又有什么問(wèn)題,為什么出錯(cuò)的總是我。”
“你把Pursuit(追求者)換成了Proxy(代理),把卓賈易換成戴勵(lì)。這就使得這個(gè)禮物變成是戴勵(lì)送的,而你剛才還肯定地說(shuō),卓賈易這個(gè)人是存在的,禮物是他買(mǎi)的,你這怎么能正確呢?”
“哦,我明白了,我這樣寫(xiě)把Pursuit追求者給忽略了,事實(shí)上應(yīng)該P(yáng)ursuit追求者通過(guò)Proxy代理送給SchoolGirl被追求者禮物,這才是合理的。那我應(yīng)該如何辦呢? SchoolGirl被追求者送的禮物是Pursuit追求者買(mǎi)的,實(shí)質(zhì)是還是追求者Pursuit送的,只是通過(guò)Proxy代理了。”
“很好,既然兩者都有相同的方法,那就意味著他們都怎樣?”
“哦,你的意思是他們都實(shí)現(xiàn)了同樣的接口?我想,我可以寫(xiě)出代碼來(lái)了。”
“小菜開(kāi)竅了。”
7.4符合實(shí)際的代碼
十分鐘后。小菜第三份代碼。
結(jié)構(gòu)圖
- //代理接口?? ??
- public ? interface ?GiveGift????
- {????
- ???? void ?giveDolls();????
- ????
- ???? void ?giveFlowers();????
- ????
- ???? void ?giveChocolate();????
- }????
- //追求者類(lèi)?? ??
- public ? class ?Pursuit? implements ?GiveGift????
- {????
- ????SchoolGirl??mm;????
- ????
- ???? public ?Pursuit(SchoolGirl?mm)????
- ????{????
- ???????? this .mm?=?mm;????
- ????}????
- ????
- ???? public ? void ?giveDolls()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你洋娃娃" );????
- ????}????
- ????
- ???? public ? void ?giveFlowers()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你鮮花" );????
- ????}????
- ????
- ???? public ? void ?giveChocolate()????
- ????{????
- ????????System.out.println(mm.name?+? "?送你巧克力" );????
- ????}????
- }????
- //代理類(lèi)?? ??
- public ? class ?Proxy? implements ?GiveGift????
- {????
- ????Pursuit?gg;????
- ????
- ???? public ?Proxy(SchoolGirl?mm)????
- ????{????
- ????????gg?=? new ?Pursuit(mm);????
- ????}????
- ????
- ???? public ? void ?giveChocolate()????
- ????{????
- ????????gg.giveChocolate();????
- ????}????
- ????
- ???? public ? void ?giveDolls()????
- ????{????
- ????????gg.giveDolls();????
- ????}????
- ????
- ???? public ? void ?giveFlowers()????
- ????{????
- ????????gg.giveFlowers();????
- ????}????
- }????
- //客戶端代碼?? ??
- public ? class ?Main????
- {????
- ???? public ? static ? void ?main(String[]?args)????
- ????{????
- ????????SchoolGirl?jiaojiao?=? new ?SchoolGirl();????
- ????????jiaojiao.setName( "李嬌嬌" );????
- ????
- ????????Proxy?daili?=? new ?Proxy(jiaojiao);????
- ????????daili.giveDolls();????
- ????????daili.giveFlowers();????
- ????????daili.giveChocolate();????
- ????}????
- }????
?
“這下好了,嬌嬌不認(rèn)識(shí)追求她的人,但卻可以通過(guò)代理人得到禮物。效果也達(dá)到了。”
“這就是代理模式。好了,我們來(lái)看看GoF對(duì)代理模式是如何描述的。”
7.5代理模式
代理模式(Proxy),為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。
代理模式(Proxy)結(jié)構(gòu)圖
- //Subject類(lèi),定義了RealSubject和Proxy的共用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy。?? ??
- public ? interface ?Subject????
- {????
- ???? public ? void ?request();????
- }????
- //RealSubject類(lèi),定義Proxy所代表的真實(shí)實(shí)體。?? ??
- public ? class ?RealSubject? implements ?Subject????
- {????
- ???? public ? void ?request()????
- ????{????
- ????????System.out.println( "真實(shí)的請(qǐng)求" );????
- ????}????
- }????
- //Proxy類(lèi),保存一個(gè)引用使用代理可以訪問(wèn)實(shí)體,并提供一個(gè)與Subject的接口相同的接口,這樣的代理可以用替代實(shí)體。?? ??
- public ? class ?Proxy? implements ?Subject????
- {????
- ????RealSubject?realSubject;????
- ????
- ???? public ? void ?request()????
- ????{????
- ???????? if ?( null ?==?realSubject)????
- ????????{????
- ????????????realSubject?=? new ?RealSubject();????
- ????????}????
- ????????realSubject.request();????
- ????}????
- }????
- //客戶端代碼?? ??
- public ? class ?Main????
- {????
- ???? public ? static ? void ?main(String[]?args)????
- ????{????
- ????????Proxy?proxy?=? new ?Proxy();????
- ????????proxy.request();????
- ????}????
- }????
7.6代理模式應(yīng)用
“那代理模式一般應(yīng)用于什么場(chǎng)合呢?”
“一般來(lái)說(shuō)可以分為以下幾種:第一,遠(yuǎn)程代理,也就是為一個(gè)對(duì)象在不同的地址空間提供局部代表。這樣可以隱藏一個(gè)對(duì)象存在于不同地址空間的事實(shí)。”
“這么抽象的說(shuō),你能不能舉個(gè)具體點(diǎn)的例子說(shuō)明一下。”
“其實(shí)你一定用過(guò)的,WebService在.NET中的應(yīng)用是怎樣做的?”
“哦,我明白什么叫遠(yuǎn)程代理了,當(dāng)我在應(yīng)用程序的項(xiàng)目中加入一個(gè)Web引用,引用一個(gè)WebService,此時(shí)會(huì)在項(xiàng)目中生成一個(gè)WebReference的文件夾和一些文件,其實(shí)它們就是代理,這就使得客戶端程序調(diào)用代理就可以解決遠(yuǎn)程訪問(wèn)的問(wèn)題。原來(lái)這就是代理模式的應(yīng)用啊。”
“第二種應(yīng)用是虛擬代理,是根據(jù)需要?jiǎng)?chuàng)建開(kāi)銷(xiāo)很大的對(duì)象。通過(guò)它來(lái)存放實(shí)例化需要很長(zhǎng)時(shí)間的真實(shí)對(duì)象。這樣就可以達(dá)到性能的最優(yōu)化,比如說(shuō)你打開(kāi)一個(gè)很大的HTML網(wǎng)頁(yè)時(shí),里面可能有很多的文字和圖片,但你還是可以很快地打開(kāi)它,此時(shí)你所看到的所有文字,但圖片卻是一張一張地下載后,才能看到的。那些未打開(kāi)的圖片框,就是通過(guò)虛擬代理來(lái)替代了真實(shí)的圖片,此時(shí)代理存儲(chǔ)了真實(shí)圖片的路徑和尺寸。”
“哦,原來(lái)瀏覽器當(dāng)中是用代理模式來(lái)優(yōu)化下載的啊。”
“第三種應(yīng)用是安全代理,用來(lái)控制真實(shí)對(duì)象訪問(wèn)時(shí)的權(quán)限。一般用于對(duì)象應(yīng)該有不同的訪問(wèn)權(quán)限的時(shí)候。第四種是智能指引,是指當(dāng)調(diào)用真實(shí)對(duì)象時(shí),代理處理另外一些事。如計(jì)算真實(shí)對(duì)象的引用次數(shù),這樣當(dāng)該對(duì)象沒(méi)有引用時(shí),可以自動(dòng)釋放它;或當(dāng)?shù)谝淮我靡粋€(gè)持久對(duì)象時(shí),將它裝入內(nèi)存;或在訪問(wèn)一個(gè)實(shí)際對(duì)象前,檢查是否已經(jīng)鎖定它,以確保其他對(duì)象不能改變它。它們都是通過(guò)代理在訪問(wèn)一個(gè)對(duì)象時(shí)附加一些內(nèi)務(wù)處理。”
“啊,原來(lái)代理可以做這么多的事情啊,我還以為它是一個(gè)很不常用的模式呢。”
“代理模式其實(shí)就是在訪問(wèn)對(duì)象時(shí)引入一定程度的間接性,因?yàn)檫@種間接性,可以附加多種用途。”
“哦,明白,說(shuō)白了,代理就是真實(shí)對(duì)象的代表。”
7.7秀才讓小六代其求婚
“好了,看會(huì)兒電視吧,好幾天沒(méi)看《武林外傳》了。”大鳥(niǎo)打開(kāi)了電視,此時(shí)武林外傳正在播放第22集。
當(dāng)播放到最后片段時(shí),劇中,郭芙蓉對(duì)呂秀才惡狠狠地說(shuō):“呂秀才,是你讓小六向我求婚的吧?”
“造物弄人!”呂秀才慘慘地答道,“這只是一個(gè)玩笑。”
“哦! ……玩笑!”郭芙蓉冷笑地說(shuō),“我殺了你!”
秀才速奔出去,郭芙蓉口中叫著“你給我站住!”跟著跑了出去……
小菜和大鳥(niǎo)看到這里,轉(zhuǎn)頭相互看著對(duì)方,小菜說(shuō):“呂秀才讓燕小六代其向郭芙蓉求婚,這不就是…”,兩人異口同聲的說(shuō):“代一理一模一式!”
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
