橋接模式 -- 分離功能層次結構和實現(xiàn)層次結構

1. 概述

橋接模式(Bridge Pattern)是一種結構型設計模式。在理解橋接模式前债蜜,我們要先能夠區(qū)分“類的功能層次結構”和“類的實現(xiàn)層次結構”。

舉一個簡單的例子,比如我們設計了一個程序置逻,它有打印字符串的功能,同時它又需要分別能夠在 windows 和 linux 上運行备绽,并且打印不同的內(nèi)容券坞。那么假定我們有一個 Program 類,類中有一個print方法肺素,那么我們會在 ProgramWinImpl 和 ProgramLiunxImpl 中分別實現(xiàn) print 方法用于打印不同的內(nèi)容恨锚,這就是我們上面說到的“類的實現(xiàn)層次結構”的拓展。假定現(xiàn)在我們需要給這個程序增加一個新功能 multiPrint倍靡,用于打印多行字符串猴伶,那么我們就會創(chuàng)建一個 MutilProgram 來繼承 Program,并且增加 multiPrint 這個方法菌瘫。這就是我們上面說到的“類的功能層次結構”的拓展蜗顽。如果對這兩種不同維度的拓展都使用簡單的繼承思想,那么我們的繼承關系將會非秤耆茫混雜、難以理解忿等。這時栖忠,我們就需要引入橋接模式,幫助我們搭建“類的功能層次結構”和“類的實現(xiàn)層次結構”之間的橋梁贸街。

2. 模式類圖

bridge-1.png

3. 模式角色

Abstraction (抽象化)
Abstraction 角色位于“類的功能層次結構”的最上層庵寞。該角色保存了Implementor角色的實例,使用Implementor角色的方法定義基本功能薛匪。

RefinedAbstraction (改善的抽象化)
RefinedAbstraction 角色負責在基礎上增加新的功能捐川。

Implementor (實現(xiàn)者)
Implementor 角色位于“類的實現(xiàn)層次結構”的最上層。它定義了用于實現(xiàn) Abstraction 角色的接口的方法逸尖。

ConcreteImplementor (具體實現(xiàn)者)
ConcreteImplementor 角色負責實現(xiàn) Implementor 角色中定義的方法古沥。

4. 代碼示例

類的功能層次結構

Display.java

Display 類是“類的功能層次結構”的最上層瘸右,表示功能的抽象。它的 impl 字段保存了實現(xiàn) Display 類的具體功能的實例岩齿。該實例通過 Display 的構造函數(shù)被傳遞給 Display 類太颤,保存在 impl 字段中。impl 字段就是類的兩個層次結構的“橋梁”盹沈。

public class Display {
    private DisplayImpl impl;

    public Display(DisplayImpl impl) {
        this.impl = impl;
    }

    public void open() {
        this.impl.rawOpen();
    }

    public void print() {
        this.impl.rawPrint();
    }

    public void close() {
        this.impl.rawClose();
    }

    public void display() {
        open();
        print();
        close();
    }
}

CountDisplay.java

CountDisplay 類是 Display 類的功能層次結構的拓展龄章,它增加了“多次顯示”的功能。

public class CountDisplay extends Display {
    public CountDisplay(DisplayImpl impl) {
        super(impl);
    }

    public void multiDisplay(int times) {
        open();
        for (int i = 0; i < times; i++) {
            print();
        }
        close();
    }
}

類的實現(xiàn)層次結構

DisplayImpl.java

DisplayImpl 是一個抽象類乞封,只聲明的對應 Display 類的三個抽象方法做裙。

public abstract class DisplayImpl {
    public abstract void rawOpen();

    public abstract void rawPrint();

    public abstract void rawClose();
}

StringDisplayImpl.java

StringDisplayImpl 類最后實現(xiàn)了 Display 的所有功能。

public class StringDisplayImpl extends DisplayImpl {
    private String string;
    private int width;

    public StringDisplayImpl(String string) {
        this.string = string;
        this.width = string.getBytes().length;
    }

    @Override
    public void rawOpen() {
        printLine();
    }

    @Override
    public void rawPrint() {
        System.out.println("|" + string + "|");
    }

    @Override
    public void rawClose() {
        printLine();
    }

    private void printLine() {
        System.out.print("+");
        for (int i = 0; i < width; i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }
}

Main.java

最后我們看一下如何調用 Display肃晚。

public class Main {
    public static void main(String[] args){
        Display d1 = new Display(new StringDisplayImpl("hello world"));
        CountDisplay d2 = new CountDisplay(new StringDisplayImpl("hello world"));

        d1.display();
        d2.display();
        d2.multiDisplay(5);
    }

}

結果

+-----------+
|hello world|
+-----------+
+-----------+
|hello world|
+-----------+
+-----------+
|hello world|
|hello world|
|hello world|
|hello world|
|hello world|
+-----------+

5. 延展閱讀

繼承是強關聯(lián)锚贱,委托是弱關聯(lián)

繼承是一種拓展類的有效手段,但是其弊端就是使父類和子類之間有很強的關聯(lián)性陷揪。如果我們想靈活的改變類之間的關系惋鸥,那么使用“委托”的概念就會顯得更合適。

以我們的代碼示例為例悍缠,所謂“委托”卦绣,就是指 Display 類自身的方法并不自己直接處理邏輯,而是交由(委托) DisplayImpl 實現(xiàn)類來處理飞蚓。

public void open() {
    this.impl.rawOpen();
}

而 DisplayImpl 類實在 Display 類的實例生成時才被作為參數(shù)傳入的滤港,所以 Display 類中方法的最終實現(xiàn)可以在此刻才被決定。這就是通過“委托”實現(xiàn)類功能的自由拓展趴拧。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溅漾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子著榴,更是在濱河造成了極大的恐慌添履,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脑又,死亡現(xiàn)場離奇詭異暮胧,居然都是意外死亡,警方通過查閱死者的電腦和手機问麸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門往衷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人严卖,你說我怎么就攤上這事席舍。” “怎么了哮笆?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵来颤,是天一觀的道長汰扭。 經(jīng)常有香客問我,道長脚曾,這世上最難降的妖魔是什么东且? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮本讥,結果婚禮上珊泳,老公的妹妹穿的比我還像新娘。我一直安慰自己拷沸,他們只是感情好色查,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撞芍,像睡著了一般秧了。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上序无,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天验毡,我揣著相機與錄音,去河邊找鬼帝嗡。 笑死晶通,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的哟玷。 我是一名探鬼主播狮辽,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼巢寡!你這毒婦竟也來了喉脖?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抑月,失蹤者是張志新(化名)和其女友劉穎树叽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谦絮,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡菱皆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挨稿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡京痢,死狀恐怖奶甘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祭椰,我是刑警寧澤臭家,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布疲陕,位于F島的核電站,受9級特大地震影響钉赁,放射性物質發(fā)生泄漏蹄殃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一你踩、第九天 我趴在偏房一處隱蔽的房頂上張望诅岩。 院中可真熱鬧,春花似錦带膜、人聲如沸吩谦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽式廷。三九已至,卻和暖如春芭挽,著一層夾襖步出監(jiān)牢的瞬間滑废,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工袜爪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蠕趁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓饿敲,卻偏偏與公主長得像妻导,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怀各,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

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

  • 1.初識橋接模式 將抽象部分與它的實現(xiàn)部分分離倔韭,使它們都可以獨立地變化。 Abstraction:抽象部分的接口瓢对。...
    王偵閱讀 913評論 0 7
  • 學習的過程中發(fā)現(xiàn)這兩個概念真的是有點區(qū)分不開寿酌,盡管可以很感性的說bridge模式要比strategy模式更復雜更具...
    小陳阿飛閱讀 1,917評論 0 1
  • 結構模式(Structural Pattern)描述如何將類或者對象結合在一起形成更大的結構。 類的結構模式:(靜...
    蘇先生Tongson閱讀 1,783評論 1 0
  • 橋接模式(結構型) 一硕蛹、橋接模式概述 橋接模式是一種很實用的結構型設計模式醇疼,如果軟件系統(tǒng)中某個類存在兩個獨立變化的...
    哈哈大圣閱讀 385評論 0 0
  • 設計模式 一、引言 假如有三個品牌的手機vivo法焰,oppo和小米秧荆,如果手機手機殼一體生產(chǎn),會是這樣的: 對應到相應...
    凱玲之戀閱讀 7,344評論 0 8