七種結(jié)構(gòu)型模式
適配器模式(Adapter Pattern)
組合模式(Composite Pattern)
裝飾器模式(Decorator Pattern)
代理模式(Proxy Pattern)
橋接模式(Bridge Pattern)
外觀模式(Facade Pattern)
享元模式(Flyweight Pattern)
所有的結(jié)構(gòu)型設(shè)計(jì)模式在邏輯上都各自不同程度的隱含了“間接”“代理”“委托”的含義 ,有的明顯,有的含蓄
強(qiáng)表現(xiàn)
適配器、裝飾器、代理、組合、橋接模式,這幾種模式比較強(qiáng)烈的表現(xiàn)了“間接”“代理”“委托”的含義
從圖中可以清楚地看得出來,他們都有“代理”的含義
適配器模式,通過繼承或者組合方式,“代理”了,被適配角色Adaptee |
裝飾器模式,通過組合的方式,"是你還有你",內(nèi)部擁有Component,代理了被裝飾的具體構(gòu)建 ConcreteComponent |
代理模式,通過組合的方式,內(nèi)部擁有RealSubject,代理了真實(shí)主題角色 |
組合模式,通過組合的方式,內(nèi)部包含葉子節(jié)點(diǎn)或者樹枝節(jié)點(diǎn),內(nèi)部“代理”了 子對象 |
橋接模式,通過組合的方式,內(nèi)部擁有Implementor,指向?qū)崿F(xiàn)者 |
如果裝飾器模式只有一個(gè)被裝飾的類ConcreteComponent,也只有一個(gè)裝飾器角色ConcreteDecorator
省略掉Decorator ,他跟代理模式的結(jié)構(gòu)可以說是一樣的
省略掉裝飾器模式結(jié)構(gòu)圖中的ConcreteDecorator角色,組合模式和裝飾器模式的結(jié)構(gòu)就完全一樣了
如果只有一種類型的ConcreteImplementor,橋接模式又與對象適配器模式相同
雖然說他們都有“代理”的含義,但是他們又有很大差別
適配器模式下,“代理”的對象是功能相近的替代方案,比如,插座適配器可以進(jìn)行插頭轉(zhuǎn)換 使得原本不兼容,不能夠一起工作的那些類能夠一起工作 |
代理模式下,“代理”的真實(shí)主題的對象RealSubject,從而對真實(shí)對象進(jìn)行隱藏,封裝 透明的對外界提供服務(wù),控制外界對這個(gè)對象的訪問 |
裝飾器模式下,“代理”的是抽象的Component構(gòu)建,能夠代理所有的ConcreteComponent類型 裝飾器和被裝飾的構(gòu)建都是Component,重點(diǎn)在于功能的擴(kuò)展,添加額外的職責(zé) |
組合模式下,“代理”的是抽象構(gòu)建Component,代理的是子對象,用于描述“整體-部分”的概念 |
橋接模式,“代理”的是實(shí)現(xiàn)角色I(xiàn)mplementor,代理的是具體的實(shí)現(xiàn),用于將抽象與實(shí)現(xiàn)進(jìn)行分離 分離后通過橋接模式進(jìn)行連接 |
他們雖然都是“代理”,但是他們的側(cè)重點(diǎn)不同,被代理的事物的性質(zhì)不同
適配器模式在代理的過程中,重點(diǎn)在于適配,不會(huì)增加額外的功能
代理模式側(cè)重于控制,當(dāng)然也通常用于增加功能
如果代理模式,代理的不是真實(shí)主題對象RealSubject,而是抽象構(gòu)建Subject,顯然,就演化成了裝飾器模式
因?yàn)榇砟J讲还饽軌蚩刂仆饨鐚φ鎸?shí)對象的訪問,他也能夠提供額外的服務(wù)
裝飾器模式則是重點(diǎn)在于功能的擴(kuò)展,增肌額外的職責(zé)
而組合模式,重點(diǎn)在于形成“整體--部分”的結(jié)構(gòu),并且對外界客戶端程序,提供一致的訪問形式
弱表現(xiàn)
享元模式和外觀模式也是一定程度的代理
享元模式,通過內(nèi)部狀態(tài)與外部狀態(tài)的分離,通過享元池中的享元對象,代理了所有的具有內(nèi)外狀態(tài)完整的對象
對客戶端來說就是有如此多的對象, 只不過內(nèi)存中卻僅有少量的對象
外觀模式在結(jié)構(gòu)上完全看不出來“代理”的含義,但是他在業(yè)務(wù)邏輯上充當(dāng)?shù)囊睬∏∈恰敖涌谌恕薄皡f(xié)調(diào)者”“控制臺”的角色
所以也可以認(rèn)為是“代理”了內(nèi)部的子系統(tǒng)
代理模式與適配器模式
代理模式和適配器模式都需要借助于內(nèi)部的“被代理”對象,或者“被適配者”對象進(jìn)行工作
也就是說他們都將自己的工作委托出去
但是代理模式中,代理者與被代理者他們擁有相同的接口,也就是擁有相同的對外呈現(xiàn),重點(diǎn)在于對真實(shí)對象的隱藏,客戶端請求的透傳,并且可以額外的增加一些控制,管理
適配器模式中,目標(biāo)對象和被適配者在接口上沒有必然聯(lián)系,比如目標(biāo)是港版插座面板,被適配者是大陸插座面板,他們的共同點(diǎn)是提供電力,但是接口卻完全不同
適配器的重點(diǎn)在于不能一起工作的類能夠一起工作
代理模式與裝飾器模式
代理模式提供與被代理的真實(shí)對象相同的訪問接口,對真實(shí)對象進(jìn)行一定的控制,也可以增加額外的服務(wù),職責(zé)
裝飾器模式也是代理了內(nèi)部真實(shí)的對象,并且擁有相同的訪問接口
但是代理模式重點(diǎn)在于增加對真實(shí)對象的控制,隱藏真實(shí)對象,一般會(huì)在代理類內(nèi)部創(chuàng)建一個(gè)真實(shí)的對象
也就是說這種代理關(guān)系在編譯時(shí)期已經(jīng)靜態(tài)確定了
代理類接受處理來自客戶端的請求,在內(nèi)部轉(zhuǎn)發(fā)到真實(shí)主題對象上
比如
//代理模式public class Proxy implements Subject{private Subject realSubject;public Proxy(){//關(guān)系在編譯時(shí)確定realSubject = new RealSubject();}public void doSth(){….realSubject.doSth();….}}
裝飾器模式在于功能的動(dòng)態(tài)增加,所以對象一般作為參數(shù)進(jìn)行傳遞,比如:
InputStream inputStream = new BufferedInputStream(new FileInputStream("........"));
這是一種在運(yùn)行期間動(dòng)態(tài)增加功能方式
適配器與外觀模式
適配器模式將一種接口轉(zhuǎn)換為另外一種接口,使得原本不能一起工作的類可以協(xié)作
外觀模式是將子系統(tǒng)的的多個(gè)接口的訪問轉(zhuǎn)換為另一種接口,使得原本復(fù)雜難用,耦合程度高的多個(gè)類有一個(gè)一致簡單的接口
他們都變成了另外一種形式的接口
所有的請求也都是委托他人進(jìn)行處理,適配器模式委托給被適配角色,外觀模式委托給子系統(tǒng)
適配器模式是為了能夠一起工作,他們原本是并不兼容的
外觀模式是為了能夠更好地更簡單的工作,他們原本是可以一起工作的
橋接模式與適配器模式
適配器模式的主要目的是讓因?yàn)榻涌诓患嫒荻荒芑ハ喙ぷ鞯念惸軌蛞黄鸸ぷ?/span>
換句話說就是他們本身不同,我用“紐帶” Adapter將他們連接起來
而橋接模式則是將原本或許緊密結(jié)合在一起的抽象與實(shí)現(xiàn),進(jìn)行分離
使她們能夠各自獨(dú)立的發(fā)展,是把連接在一起的兩個(gè)事物,拆分開來
然后用“紐帶”“橋梁”(也就是對象的引用)將他們連接起來
適配器模式就好比張三和王五不認(rèn)識,李四介紹他們認(rèn)識
橋梁模式好比張三和王五成天黏在一起活干得不好太亂套,李四說以后我作為接口人,你倆各干各的吧
雖然看起來都是兩個(gè)人干活,中間一個(gè)聯(lián)系人,但是含義卻是完全不同
橋接模式與裝飾器模式
裝飾器模式中,使用組合而不是繼承來對類的功能進(jìn)行擴(kuò)展
避免了類的個(gè)數(shù)的爆炸增長,與橋梁模式的結(jié)果不約而同
他們都解決了類爆炸增長的問題,都避免了過多的沒必要的子類
裝飾器模式側(cè)重于功能的動(dòng)態(tài)增加,將額外的功能提取到子類中
通過不同的排列組合,形成一個(gè)遞歸的調(diào)用方式,以動(dòng)態(tài)的增加各部分的功能
橋梁模式是將原本系統(tǒng)中的實(shí)現(xiàn)細(xì)節(jié)抽取出來,比如原來抽象概念與實(shí)例化全部都是一個(gè)類層次結(jié)構(gòu)中
把所有的實(shí)現(xiàn)細(xì)節(jié),比如示例中的平臺相關(guān)實(shí)現(xiàn),抽取出來,進(jìn)行分離,達(dá)到抽象與實(shí)現(xiàn)分離的目的
所以雖然他們都可以解決子類爆炸式增長、不易擴(kuò)展的問題
但是他們的出發(fā)點(diǎn)完全不同
一個(gè)關(guān)注于功能的動(dòng)態(tài)擴(kuò)展組合
一個(gè)關(guān)注于抽象與實(shí)現(xiàn)的分離,獲得更多的靈活性
總結(jié)
所有的結(jié)構(gòu)型模式的都離不開“分離,解耦”的概念
而“分離,解耦”之后,又通過某種形式建立聯(lián)系,比如“組合”
抽象與實(shí)現(xiàn)進(jìn)行分離,分離就意味著獨(dú)立,獨(dú)立就意味著可以單獨(dú)發(fā)展,橋接模式
對于分離的事物通過委托的形式托付工作,就可以在中間提供更多的服務(wù),代理模式
而分離的兩個(gè)事物也可以通過一定形式的結(jié)合、轉(zhuǎn)換進(jìn)而一起協(xié)同工作,適配器模式
將一個(gè)對象的多個(gè)功能點(diǎn)進(jìn)行分離,從而能夠動(dòng)態(tài)的組合以形成更強(qiáng)大的功能,裝飾器模式
將事物自身內(nèi)部核心狀態(tài)與外部狀態(tài)進(jìn)行分離,進(jìn)而減少核心狀態(tài)的存儲(chǔ)運(yùn)行消耗,享元模式
將客戶端與子系統(tǒng)的耦合交互進(jìn)行分離,抽象出來一個(gè)新的接入點(diǎn),外觀Facade,降低耦合,外觀模式
分離開的多種事物,如果他們有“整體--部分”的關(guān)系,可以將它們組合在一起,形成更復(fù)雜的整體結(jié)構(gòu),組合模式
(ps:上面的分離指分開的,不耦合在一起,不是特指原本是一個(gè)整體,被分成兩部分)
以上各個(gè)部分的差異對比點(diǎn)主要根據(jù)設(shè)計(jì)模式的最初意圖、動(dòng)機(jī),設(shè)計(jì)模式本就是設(shè)計(jì)原則的實(shí)現(xiàn)化角色
對于任何的結(jié)構(gòu),你都可以按照你自己的想法去使用、拓展,當(dāng)然,前提是更合適或者更優(yōu)秀
否則您那是瞎用
比如代理模式與裝飾器模式本就很類似,如果你將代理模式的真實(shí)對象也是作為參數(shù)進(jìn)行傳遞
也是用來動(dòng)態(tài)的增加職責(zé),那么就成了裝飾器模式,所以再回頭,你說你的是代理模式還是裝飾器模式?
這么看這個(gè)名字代理還是裝飾器又有什么大的區(qū)別的呢?都只是用來敘述而已
但是如果你這么做還非要說是代理模式,有一個(gè)很大的問題就是和同事、領(lǐng)導(dǎo)溝通起來就特別費(fèi)勁了,說不定還會(huì)吵起來...
所以,除非你有更好更合適的選擇,或者改變
否則,一定要盡量按照模式原本的意圖和動(dòng)機(jī)去使用某種模式