设计模式二(转载)
在閱讀過程中有任何問題,請及時聯(lián)系:egg。
郵箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef
如有轉(zhuǎn)載,請說明出處:http://blog.csdn.net/zhangerqing
我們接著討論設(shè)計模式,上篇文章我講完了5種創(chuàng)建型模式,這章開始,我將講下7種結(jié)構(gòu)型模式:適配器模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。其中對象的適配器模式是各種模式的起源,我們看下面的圖:
6、適配器模式(Adapter)
?適配器模式將某個類的接口轉(zhuǎn)換成客戶端期望的另一個接口表示,目的是消除由于接口不匹配所造成的類的兼容性問題。主要分為三類:類的適配器模式、對象的適配器模式、接口的適配器模式。首先,我們來看看類的適配器模式,先看類圖:
核心思想就是:有一個Source類,擁有一個方法,待適配,目標(biāo)接口時Targetable,通過Adapter類,將Source的功能擴(kuò)展到Targetable里,看代碼:
[java] view plaincopyAdapter類繼承Source類,實現(xiàn)Targetable接口,下面是測試類:
[java] view plaincopy輸出:
this is original method!
this is the targetable method!
這樣Targetable接口的實現(xiàn)類就具有了Source類的功能。
對象的適配器模式
基本思路和類的適配器模式相同,只是將Adapter類作修改,這次不繼承Source類,而是持有Source類的實例,以達(dá)到解決兼容性的問題。看圖:
?
只需要修改Adapter類的源碼即可:
[java] view plaincopy測試類:
[java] view plaincopy輸出與第一種一樣,只是適配的方法不同而已。
第三種適配器模式是接口的適配器模式, 接口的適配器是這樣的:有時我們寫的一個接口中有多個抽象方法,當(dāng)我們寫該接口的實現(xiàn)類時,必須實現(xiàn)該接口的所有方法,這明顯有時比較浪費(fèi),因為并不是所 有的方法都是我們需要的,有時只需要某一些,此處為了解決這個問題,我們引入了接口的適配器模式,借助于一個抽象類,該抽象類實現(xiàn)了該接口,實現(xiàn)了所有的 方法,而我們不和原始的接口打交道,只和該抽象類取得聯(lián)系,所以我們寫一個類,繼承該抽象類,重寫我們需要的方法就行。看一下類圖:
這個很好理解,在實際開發(fā)中,我們也常會遇到這種接口中定義了太多的方法,以致于有時我們在一些實現(xiàn)類中并不是都需要。看代碼:
[java] view plaincopy抽象類Wrapper2:
[java] view plaincopy測試輸出:
the sourceable interface's first Sub1!
the sourceable interface's second Sub2!
達(dá)到了我們的效果!
?講了這么多,總結(jié)一下三種適配器模式的應(yīng)用場景:
類的適配器模式:當(dāng)希望將一個類轉(zhuǎn)換成滿足另一個新接口的類時,可以使用類的適配器模式,創(chuàng)建一個新類,繼承原有的類,實現(xiàn)新的接口即可。
對象的適配器模式:當(dāng)希望將一個對象轉(zhuǎn)換成滿足另一個新接口的對象時,可以創(chuàng)建一個Wrapper類,持有原類的一個實例,在Wrapper類的方法中,調(diào)用實例的方法就行。
接口的適配器模式:當(dāng)不希望實現(xiàn)一個接口中所有的方法時,可以創(chuàng)建一個抽象類Wrapper,實現(xiàn)所有方法,我們寫別的類的時候,繼承抽象類即可。
7、裝飾模式(Decorator)
顧名思義,裝飾模式就是給一個對象增加一些新的功能,而且是動態(tài)的,要求裝飾對象和被裝飾對象實現(xiàn)同一個接口,裝飾對象持有被裝飾對象的實例,關(guān)系圖如下:
Source類是被裝飾類,Decorator類是一個裝飾類,可以為Source類動態(tài)的添加一些功能,代碼如下:
[java] view plaincopy測試類:
[java] view plaincopy輸出:
before decorator!
the original method!
after decorator!
裝飾器模式的應(yīng)用場景:
1、需要擴(kuò)展一個類的功能。
2、動態(tài)的為一個對象增加功能,而且還能動態(tài)撤銷。(繼承不能做到這一點,繼承的功能是靜態(tài)的,不能動態(tài)增刪。)
缺點:產(chǎn)生過多相似的對象,不易排錯!
8、代理模式(Proxy)
其 實每個模式名稱就表明了該模式的作用,代理模式就是多一個代理類出來,替原對象進(jìn)行一些操作,比如我們在租房子的時候回去找中介,為什么呢?因為你對該地 區(qū)房屋的信息掌握的不夠全面,希望找一個更熟悉的人去幫你做,此處的代理就是這個意思。再如我們有的時候打官司,我們需要請律師,因為律師在法律方面有專 長,可以替我們進(jìn)行操作,表達(dá)我們的想法。先來看看關(guān)系圖:
根據(jù)上文的闡述,代理模式就比較容易的理解了,我們看下代碼:
[java] view plaincopy測試類:
[java] view plaincopy輸出:
before proxy!
the original method!
after proxy!
代理模式的應(yīng)用場景:
如果已有的方法在使用的時候需要對原有的方法進(jìn)行改進(jìn),此時有兩種辦法:
1、修改原有的方法來適應(yīng)。這樣違反了“對擴(kuò)展開放,對修改關(guān)閉”的原則。
2、就是采用一個代理類調(diào)用原有的方法,且對產(chǎn)生的結(jié)果進(jìn)行控制。這種方法就是代理模式。
使用代理模式,可以將功能劃分的更加清晰,有助于后期維護(hù)!
9、外觀模式(Facade)
外觀模式是為了解決類與類之家的依賴關(guān)系的,像spring一樣,可以將類和類之間的關(guān)系配置到配置文件中,而外觀模式就是將他們的關(guān)系放在一個Facade類中,降低了類類之間的耦合度,該模式中沒有涉及到接口,看下類圖:(我們以一個計算機(jī)的啟動過程為例)
我們先看下實現(xiàn)類:
[java] view plaincopyUser類如下:
[java] view plaincopy輸出:
start the computer!
cpu startup!
memory startup!
disk startup!
start computer finished!
begin to close the computer!
cpu shutdown!
memory shutdown!
disk shutdown!
computer closed!
如 果我們沒有Computer類,那么,CPU、Memory、Disk他們之間將會相互持有實例,產(chǎn)生關(guān)系,這樣會造成嚴(yán)重的依賴,修改一個類,可能會帶 來其他類的修改,這不是我們想要看到的,有了Computer類,他們之間的關(guān)系被放在了Computer類里,這樣就起到了解耦的作用,這,就是外觀模 式!
10、橋接模式(Bridge)
橋接模式就是把事物和其具體實現(xiàn)分開,使他們可以各自獨(dú)立的變化。橋接的用意是:將抽象化與實現(xiàn)化解耦,使得二者可以獨(dú)立變化, 像我們常用的JDBC橋DriverManager一樣,JDBC進(jìn)行連接數(shù)據(jù)庫的時候,在各個數(shù)據(jù)庫之間進(jìn)行切換,基本不需要動太多的代碼,甚至絲毫不 用動,原因就是JDBC提供統(tǒng)一接口,每個數(shù)據(jù)庫提供各自的實現(xiàn),用一個叫做數(shù)據(jù)庫驅(qū)動的程序來橋接就行了。我們來看看關(guān)系圖:
實現(xiàn)代碼:
先定義接口:
[java] view plaincopy分別定義兩個實現(xiàn)類:
[java] view plaincopy定義一個橋,持有Sourceable的一個實例:
[java] view plaincopy測試類:
[java] view plaincopyoutput:
this is the first sub!
this is the second sub!
這樣,就通過對Bridge類的調(diào)用,實現(xiàn)了對接口Sourceable的實現(xiàn)類SourceSub1和SourceSub2的調(diào)用。接下來我再畫個圖,大家就應(yīng)該明白了,因為這個圖是我們JDBC連接的原理,有數(shù)據(jù)庫學(xué)習(xí)基礎(chǔ)的,一結(jié)合就都懂了。
11、組合模式(Composite)
組合模式有時又叫部分-整體模式在處理類似樹形結(jié)構(gòu)的問題時比較方便,看看關(guān)系圖:
直接來看代碼:
[java] view plaincopy使用場景:將多個對象組合在一起進(jìn)行操作,常用于表示樹形結(jié)構(gòu)中,例如二叉樹,數(shù)等。
12、享元模式(Flyweight)
享元模式的主要目的是實現(xiàn)對象的共享,即共享池,當(dāng)系統(tǒng)中對象多的時候可以減少內(nèi)存的開銷,通常與工廠模式一起使用。
FlyWeightFactory 負(fù)責(zé)創(chuàng)建和管理享元單元,當(dāng)一個客戶端請求時,工廠需要檢查當(dāng)前對象池中是否有符合條件的對象,如果有,就返回已經(jīng)存在的對象,如果沒有,則創(chuàng)建一個新對 象,FlyWeight是超類。一提到共享池,我們很容易聯(lián)想到Java里面的JDBC連接池,想想每個連接的特點,我們不難總結(jié)出:適用于作共享的一些 個對象,他們有一些共有的屬性,就拿數(shù)據(jù)庫連接池來說,url、driverClassName、username、password及dbname,這 些屬性對于每個連接來說都是一樣的,所以就適合用享元模式來處理,建一個工廠類,將上述類似屬性作為內(nèi)部數(shù)據(jù),其它的作為外部數(shù)據(jù),在方法調(diào)用時,當(dāng)做參 數(shù)傳進(jìn)來,這樣就節(jié)省了空間,減少了實例的數(shù)量。
看個例子:
看下數(shù)據(jù)庫連接池的代碼:
[java] view plaincopy通過連接池的管理,實現(xiàn)了數(shù)據(jù)庫連接的共享,不需要每一次都重新創(chuàng)建連接,節(jié)省了數(shù)據(jù)庫重新創(chuàng)建的開銷,提升了系統(tǒng)的性能!本章講解了7種結(jié)構(gòu)型模式,因為篇幅的問題,剩下的11種行為型模式,我們將另起篇章,敬請讀者朋友們持續(xù)關(guān)注!
有問題請聯(lián)系egg:
email:xtfggef@gmail.com? ? 微博:http://weibo.com/xtfggef
轉(zhuǎn)載于:https://www.cnblogs.com/lr393993507/p/4796892.html
總結(jié)
- 上一篇: Android笔记(二十五) ListV
- 下一篇: scanf从文件中读入,printf写入