大话设计模式—桥接模式
橋接(Bridge)是用于把抽象化與實現(xiàn)化解耦,使得二者可以獨立變化。這種類型的設(shè)計模式屬于結(jié)構(gòu)型模式,它通過提供抽象化和實現(xiàn)化之間的橋接結(jié)構(gòu),來實現(xiàn)二者的解耦。主要解決:在有多種可能會變化的情況下,用繼承會造成類爆炸問題,擴(kuò)展起來不靈活。這種模式涉及到一個作為橋接的接口,使得實體類的功能獨立于接口實現(xiàn)類。這兩種類型的類可被結(jié)構(gòu)化改變而互不影響。
大話設(shè)計模式中程杰老師給出的定義是,橋接模式:將抽象部分與實現(xiàn)部分分離,使它們都可以獨立的變化。
首先我們來看一個問題:現(xiàn)在我有一個N品牌一個M品牌的手機(jī),兩個品牌的手機(jī)都有兩種功能:游戲和通訊錄,我們該如何實現(xiàn)?
依據(jù)面向?qū)ο蟮睦碚撛O(shè)計,我們有兩種設(shè)計思想:
實現(xiàn)一:先有一個品牌,多個品牌就抽象出一個品牌抽象類,對于每個功能,就都繼承各自的品牌;
實現(xiàn)二:先有功能,多個功能就可以抽象出一個抽象功能類,對于每個手機(jī)品牌,分別去繼承各個功能;
上面的設(shè)計完美的遵循了面向?qū)ο蟮脑瓌t,但是,問題也隨之而來,如果我現(xiàn)在需要給每個品牌都增加一個MP3播放器功能,我們該怎么辦?
對于實現(xiàn)一,我們需要在每個品牌下面分別增加一個MP3播放器功能;對于實現(xiàn)二,我們需要在手機(jī)軟件下增加一個抽象的MP3播放器功能,然后各個手機(jī)品牌再分別去繼承這個功能。
如果我們需要再增加一個手機(jī)品牌呢?那我們要改動的地方就越來越多了。顯然這種設(shè)計似乎有問題的。
但我們學(xué)會使用面向?qū)ο蟮睦^承時,確實感覺它非常強(qiáng)大,但是并不是所有的情況都可以使用面向?qū)ο蟮睦^承,而且有很多情況下,使用繼承會帶來麻煩。比如,對象的繼承關(guān)系是在編譯時就定義好了,所以無法在運行時改變從父類繼承的實現(xiàn)。子類實現(xiàn)與它的父類有非常緊密的依賴關(guān)系,以至于父類實現(xiàn)中的任何變化都必然會導(dǎo)致子類發(fā)生變化。當(dāng)你需要復(fù)用子類時,如果繼承下來的實現(xiàn)不適合解決新的問題,則父類必須重寫或被其它更適合的類替換。這種依賴關(guān)系限制了靈活性并最終限制了復(fù)用性。
就像我們上面的兩種實現(xiàn),如果不斷地增加新的手機(jī)品牌和功能,類會越來越多。怎么解決呢?面向?qū)ο笤O(shè)計中還有一個很重要的原則合成/聚合復(fù)用原則,即優(yōu)先使用對象合成/聚合,而不是類繼承。
合成表示一種強(qiáng)的擁有關(guān)系,體現(xiàn)了嚴(yán)格的部分和整體的關(guān)系,部分和整體的生命周期一樣,打個比方:人有兩個胳膊,胳膊和人就是部分和整體的關(guān)系,人去世了,那么胳膊也就沒用了,也就是說胳膊和人的生命周期是相同的,合成關(guān)系用實心的菱形+實線來表示。
合成/聚合復(fù)用規(guī)則的好處:優(yōu)先使用對象的合成/聚合將有助于你保持每個類被封裝,并被集中在單個任務(wù)上。這樣類和類繼承層次會保持在一個較小的規(guī)模,并且不太可能增長為不可控制的龐然大物。
下面我么來看看遵循合成/聚合復(fù)用規(guī)則的實現(xiàn)三:
橋接模式的核心意圖就是把這些實現(xiàn)獨立出來,讓它們各自的變化。這就使得每種實現(xiàn)的變化不會影響其它的實現(xiàn),從而達(dá)到應(yīng)對變化的目的。
代碼實現(xiàn):
package com.bridge;public abstract class Implementor {public abstract void operation();} package com.bridge;public class ConcreteImplementorA extends Implementor {@Overridepublic void operation() {System.out.println("具體實現(xiàn)A執(zhí)行");}} package com.bridge;public class ConcreteImplementorB extends Implementor {@Overridepublic void operation() {System.out.println("具體實現(xiàn)B執(zhí)行");}} package com.bridge;public abstract class Abstraction {protected Implementor implementor;public void setImplementor(Implementor implementor){this.implementor = implementor;}public void operation(){implementor.operation();}} package com.bridge;public class RefinedAbstraction extends Abstraction {public void operation(){implementor.operation();}} package com.bridge;public class BridgePatternDemo {public static void main(String[] args) {Abstraction ab = new RefinedAbstraction();ab.setImplementor(new ConcreteImplementorA());ab.operation();ab.setImplementor(new ConcreteImplementorB());ab.operation();}}運行結(jié)果:
具體實現(xiàn)A執(zhí)行 具體實現(xiàn)B執(zhí)行應(yīng)用實例: 墻上的開關(guān),可以看到的開關(guān)是抽象的,不用管里面具體怎么實現(xiàn)的。
優(yōu)點:
1、抽象和實現(xiàn)的分離。
2、優(yōu)秀的擴(kuò)展能力。
3、實現(xiàn)細(xì)節(jié)對客戶透明。
缺點:
橋接模式的引入會增加系統(tǒng)的理解與設(shè)計難度,由于聚合關(guān)聯(lián)關(guān)系建立在抽象層,要求開發(fā)者針對抽象進(jìn)行設(shè)計與編程。
使用場景:
1、如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的繼承聯(lián)系,通過橋接模式可以使它們在抽象層建立一個關(guān)聯(lián)關(guān)系。
2、對于那些不希望使用繼承或因為多層次繼承導(dǎo)致系統(tǒng)類的個數(shù)急劇增加的系統(tǒng),橋接模式尤為適用。
3、一個類存在兩個獨立變化的維度,且這兩個維度都需要進(jìn)行擴(kuò)展,對于兩個獨立變化的維度,使用橋接模式再適合不過了。
總結(jié)
以上是生活随笔為你收集整理的大话设计模式—桥接模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大话设计模式—组合模式
- 下一篇: 大话设计模式—命令模式