重學(xué)設(shè)計模式之橋接模式

橋接模式

定義

將抽象部分與它的實現(xiàn)部分分離理逊,使它們都可以獨立地變化肴裙。它是一種對象結(jié)構(gòu)型模式,又稱為柄體(Handle and Body)模式或接口(Interface)模式鸽心。

上面的定義太簡單了點,并不能很好的解釋什么是橋接模式工猜,看了很多文章覺得還是 LoveLin的解釋最為直接。

試想一下菱蔬,當(dāng)我們在繪畫時需要大中小三種型號的畫筆篷帅,并且能繪制12種顏色。當(dāng)我們選擇蠟筆時拴泌,為了滿足這個需求魏身,我們需要 12*3=36 支蠟筆。而同樣的情況蚪腐,如果我們選擇油彩筆時箭昵,我們僅需3支不同型號的油彩筆,配合12種不同的顏料就可以了回季,總共需要 3+12=15 個物品宙枷。而且當(dāng)我們需要增加一種型號的畫筆并且也需要繪制12種顏色掉房,蠟筆需要增加12支茧跋,而油彩筆僅需要增加一支不同型號的筆就行慰丛。為什么同樣一個需求,選擇不同的畫筆會有不同的結(jié)果呢瘾杭?

這里我們注意到繪畫需求中對畫筆有兩個屬性的需求诅病,型號與顏色,這兩個屬性都是可變可拓展的粥烁,選擇蠟筆時每一支蠟筆上這兩個屬性都非常明確贤笆,這就導(dǎo)致了兩種屬性有多少種組合,我們就需要多少支蠟筆讨阻。而相對的芥永,選擇油彩筆時,這兩個屬性是分開的钝吮,油彩筆僅僅具有型號的屬性埋涧,而顏色的屬性由顏料提供。

這就是橋接模式最生動的演示奇瘦,當(dāng)我們在軟件開發(fā)時棘催,某一個類存在兩個獨立變化的維度時,通過橋接模式耳标,可以將這兩個維度分離出來醇坝,使兩者可以單獨擴展變化,讓系統(tǒng)更符合“單一職責(zé)”原則次坡。

UML圖

上面是橋接模式最常見的結(jié)構(gòu)圖呼猪,它包含下面幾個角色:

  • Abstraction(抽象類):用于定義抽象類的接口,它一般是抽象類而不是接口砸琅,其中定義了一個Implementor(實現(xiàn)類接口)類型的對象并可以維護該對象宋距,它與Implementor之間具有關(guān)聯(lián)關(guān)系,它既可以包含抽象業(yè)務(wù)方法明棍,也可以包含具體業(yè)務(wù)方法乡革。
  • RefinedAbstraction(擴充抽象類):擴充由Abstraction定義的接口,通常情況下它不再是抽象類而是具體類摊腋,它實現(xiàn)了在Abstraction中聲明的抽象業(yè)務(wù)方法沸版,在RefinedAbstraction中可以調(diào)用在Implementor中定義的業(yè)務(wù)方法。
  • Implementor(實現(xiàn)類接口):定義實現(xiàn)類的接口兴蒸,這個接口不一定要與Abstraction的接口完全一致视粮,事實上這兩個接口可以完全不同,一般而言橙凳,Implementor接口僅提供基本操作蕾殴,而Abstraction定義的接口可能會做更多更復(fù)雜的操作笑撞。Implementor接口對這些基本操作進行了聲明,而具體實現(xiàn)交給其子類钓觉。通過關(guān)聯(lián)關(guān)系茴肥,在Abstraction中不僅擁有自己的方法,還可以調(diào)用到Implementor中定義的方法荡灾,使用關(guān)聯(lián)關(guān)系來替代繼承關(guān)系瓤狐。
  • ConcreteImplementor(具體實現(xiàn)類):具體實現(xiàn)Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同實現(xiàn)批幌,在程序運行時础锐,ConcreteImplementor對象將替換其父類對象,提供給抽象類具體的業(yè)務(wù)操作方法荧缘。

PS: 上面的介紹 copy的皆警,解釋的很書面,讀不慣的還是直接看代碼吧 ??

具體到我們前面的例子截粗,Abstraction對應(yīng)的就是油彩筆的抽象對象信姓,具有型號這個屬性,RefinedAbstraction對應(yīng)的就是具體三種型號的油彩筆桐愉,Implementor對應(yīng)的就是顏料的抽象對象财破,ConcreteImplementor對應(yīng)的就是具體的有不同顏色的顏料。

代碼

//Abstraction抽象類从诲,保持Implementor的引用
public abstract class Abstraction {

    protected Implementor impl;

    public void setImpl(Implementor impl){
        this.impl = impl;
    }
    
    //抽象操作方法
    public abstract void operation();
}


//Implementor 接口
public interface Implementor {

    void operationImpl();
}


//Abstraction抽象類的具體實現(xiàn)
public class DefindAbstraction extends Abstraction {
    @Override
    public void operation() {
        impl.operationImpl();
    }
}


//Implementor 接口的具體實現(xiàn)
public class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("this is ConcreteImplementorA operation!");
    }
}

//Implementor 接口的具體實現(xiàn)
public class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("this is ConcreteImplementorB operation!");
    }
}

客戶端調(diào)用代碼

public class Client {

    public static void main(String[] args) {
        Abstraction abstraction;
        Implementor implementor;

        abstraction = new DefindAbstraction();
        implementor = new ConcreteImplementorA();
        abstraction.setImpl(implementor);
        abstraction.operation();

        implementor = new ConcreteImplementorB();
        abstraction.setImpl(implementor);
        abstraction.operation();
    }
}

調(diào)用結(jié)果

this is ConcreteImplementorA operation!
this is ConcreteImplementorB operation!

創(chuàng)建不同維度的具體實現(xiàn)左痢,通過橋接模式配合使用極大的簡化了系統(tǒng)復(fù)雜度。

實例

老規(guī)矩系洛,還是來一個實例演示一下

某軟件公司欲開發(fā)一個數(shù)據(jù)轉(zhuǎn)換工具俊性,可以將數(shù)據(jù)庫中的數(shù)據(jù)轉(zhuǎn)換成多種文件格式,例如txt描扯、xml定页、pdf等格式,同時該工具需要支持多種不同的數(shù)據(jù)庫绽诚。試使用橋接模式對其進行設(shè)計典徊。

分析需求可知,這里數(shù)據(jù)轉(zhuǎn)換的類型是一個維度恩够,支持的數(shù)據(jù)庫類型也是一個維度卒落,分離兩個維度進行設(shè)計。

UML圖

代碼

//抽象類 保持一個DaProviderImp的引用
public abstract class DataParser {

    protected DataProviderImp dpi;

    public void setDpi(DataProviderImp dpi) {
        this.dpi = dpi;
    }

    public abstract void parseData();
}



//DataProviderImp 接口
public interface DataProviderImp {

    String readData();
}

具體實現(xiàn)如下

public class TXTDataParser extends DataParser {
    @Override
    public void parseData() {
        String str = dpi.readData();
        System.out.println("Parse "+str+" to TXT");
        System.out.println("---------------------------------------");
    }
}


public class XMLDataParser extends DataParser {
    @Override
    public void parseData() {
        String str = dpi.readData();
        System.out.println("Parse "+str+" to XML");
        System.out.println("---------------------------------------");
    }
}

...


public class OracleDataProvider implements DataProviderImp {

    @Override
    public String readData() {
        System.out.println("Connect DB ---- Oracle");
        System.out.println("Read Data from Oracle");
        return "Data from Oracle";
    }
}


public class MysqlDataProvider implements DataProviderImp {
    @Override
    public String readData() {
        System.out.println("Connect DB ---- Mysql");
        System.out.println("Read Data from Mysql");
        return "Data from Mysql";
    }
}

...

客戶端代碼如下

public class Client {

    public static void main(String[] args){
        DataParser dataParser;
        DataProviderImp dataProviderImp;

        dataParser = new TXTDataParser();
        dataProviderImp = new OracleDataProvider();
        dataParser.setDpi(dataProviderImp);
        dataParser.parseData();

        dataParser = new XMLDataParser();
        dataProviderImp = new MysqlDataProvider();
        dataParser.setDpi(dataProviderImp);
        dataParser.parseData();

        dataParser = new PDFDataParser();
        dataProviderImp = new SqlServerDataProvider();
        dataParser.setDpi(dataProviderImp);
        dataParser.parseData();
    }
}

運行結(jié)果如下

Connect DB ---- Oracle
Read Data from Oracle
Parse Data from Oracle to TXT
---------------------------------------
Connect DB ---- Mysql
Read Data from Mysql
Parse Data from Mysql to XML
---------------------------------------
Connect DB ---- SqlServer
Read Data from SqlServer
Parse Data from SqlServer to PDF
---------------------------------------

小結(jié)

LovaLin的文章中曾提出過如果有兩個以上的維度該怎么解決蜂桶,相信看完橋接模式的所有代碼后儡毕,大家應(yīng)該有個答案,兩個維度或多個維度扑媚,多出的維度都可以分離出一個實現(xiàn)部分腰湾,通過抽象部分關(guān)聯(lián)來解決雷恃。

橋接模式極大的提高了提供的擴展性,且大大減少了系統(tǒng)代碼量费坊,分離多個維度更符合“單一職責(zé)”原則倒槐,且各個維度的擴展都不用修改原系統(tǒng)代碼,符合“開閉原則”葵萎。但橋接模式的使用也會一定程度上增加系統(tǒng)的理解與設(shè)計難度导犹,需要有一定的經(jīng)驗才能很好的分別出系統(tǒng)的不同維度。


源碼:https://github.com/lichenming0516/DesignPattern

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羡忘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子磕昼,更是在濱河造成了極大的恐慌卷雕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件票从,死亡現(xiàn)場離奇詭異漫雕,居然都是意外死亡,警方通過查閱死者的電腦和手機峰鄙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門浸间,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吟榴,你說我怎么就攤上這事魁蒜。” “怎么了吩翻?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵兜看,是天一觀的道長。 經(jīng)常有香客問我狭瞎,道長细移,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任熊锭,我火速辦了婚禮弧轧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碗殷。我一直安慰自己精绎,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布亿扁。 她就那樣靜靜地躺著捺典,像睡著了一般。 火紅的嫁衣襯著肌膚如雪从祝。 梳的紋絲不亂的頭發(fā)上襟己,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天引谜,我揣著相機與錄音,去河邊找鬼擎浴。 笑死员咽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贮预。 我是一名探鬼主播贝室,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仿吞!你這毒婦竟也來了滑频?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤唤冈,失蹤者是張志新(化名)和其女友劉穎峡迷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體你虹,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡绘搞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了傅物。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夯辖。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖董饰,靈堂內(nèi)的尸體忽然破棺而出蒿褂,到底是詐尸還是另有隱情,我是刑警寧澤尖阔,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布贮缅,位于F島的核電站,受9級特大地震影響介却,放射性物質(zhì)發(fā)生泄漏谴供。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一齿坷、第九天 我趴在偏房一處隱蔽的房頂上張望桂肌。 院中可真熱鬧,春花似錦永淌、人聲如沸崎场。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谭跨。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間螃宙,已是汗流浹背蛮瞄。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谆扎,地道東北人挂捅。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像堂湖,于是被迫代替她去往敵國和親闲先。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 在正式介紹橋接模式之前无蜂,我先跟大家談?wù)剝煞N常見文具的區(qū)別伺糠,它們是毛筆和蠟筆。假如我們需要大中小3種型號的畫筆酱讶,能夠...
    justCode_閱讀 1,772評論 0 7
  • 1 場景問題# 1.1 發(fā)送提示消息## 考慮這樣一個實際的業(yè)務(wù)功能:發(fā)送提示消息退盯。基本上所有帶業(yè)務(wù)流程處理的系統(tǒng)...
    七寸知架構(gòu)閱讀 5,017評論 5 63
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是橋接模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 優(yōu)點和缺點 適用環(huán)境 模式應(yīng)用 一泻肯、...
    w1992wishes閱讀 1,761評論 0 6
  • 1.介紹 橋接模式灶挟,又稱為橋梁模式,是結(jié)構(gòu)型設(shè)計模式之一毒租。在現(xiàn)實生活中大家都知道“橋梁”是連接河道兩岸的主要交通樞...
    四會歌神陳子豪閱讀 5,330評論 3 18
  • 設(shè)計模式匯總 一稚铣、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用浪南、多...
    MinoyJet閱讀 3,948評論 1 15