結(jié)構(gòu)型-橋接(Bridge)

橋接(Bridge)

[TOC]

定義

橋梁模式(Bridge Pattern)也叫做橋接模式,是一個(gè)比較簡單的模式,其定義如下:Decouple an abstraction from its implementation so that the two can vary independently.(將抽象和實(shí)現(xiàn)解耦,使得兩者可以獨(dú)立地變化。

這話的核心在于如何去解耦,抽象者引用實(shí)現(xiàn)者玩讳,需要更換能力只用更換實(shí)現(xiàn)者即可,就好像是Android中ListView的Adapter一樣嚼贡,set進(jìn)去的是由開發(fā)者實(shí)現(xiàn)的熏纯,如果想要更換邏輯,可以重新設(shè)置新的adapter即可粤策,listView通過對(duì)adapter的抽象方法樟澜,開發(fā)者內(nèi)聚自己的實(shí)現(xiàn)即可

要實(shí)現(xiàn)這樣一個(gè)設(shè)計(jì)模式,需要如下幾個(gè)步驟:

  • Abstraction——抽象化角色:它的主要職責(zé)是定義出該角色的行為,同時(shí)保存一個(gè)對(duì)實(shí)現(xiàn)化角色的引用秩贰,該角色一般是抽象類
  • Implementor——實(shí)現(xiàn)化角色:它是接口或者抽象類霹俺,定義角色必需的行為和屬性
  • RefinedAbstraction——修正抽象化角色:它引用實(shí)現(xiàn)化角色對(duì)抽象化角色進(jìn)行修正
  • ConcreteImplementor——具體實(shí)現(xiàn)化角色:它實(shí)現(xiàn)接口或抽象類定義的方法和屬性

書上的解釋給我的感覺很官方,有些晦澀毒费,下面我來談一談我對(duì)這個(gè)橋接設(shè)計(jì)模式的理解

根據(jù)設(shè)計(jì)原則丙唧,在進(jìn)行軟件設(shè)計(jì)的時(shí)候,我們需要盡量不變動(dòng)上層模塊觅玻,減少上層對(duì)底層模塊的耦合性想际,盡可能的內(nèi)聚模塊內(nèi)的功能,弱耦合溪厘,高內(nèi)聚的關(guān)系的結(jié)果其實(shí)就是對(duì)修改關(guān)閉胡本,對(duì)擴(kuò)展開放的原則,換成語言上的理解其實(shí)就是我們的業(yè)務(wù)流程畸悬,盡量直接使用抽象或者接口來完成業(yè)務(wù)工作侧甫,這樣業(yè)務(wù)上層模塊對(duì)底層業(yè)務(wù)實(shí)現(xiàn)的持有其實(shí)就是一個(gè)抽象類或者接口,那么當(dāng)我們?cè)跀U(kuò)展業(yè)務(wù)能力或者更換業(yè)務(wù)實(shí)現(xiàn)邏輯時(shí)候蹋宦,就可以做到很少改動(dòng)甚至不改動(dòng)的情況就完成的軟件的迭代和更新~

簡單場景使用

老聯(lián)盟了披粟,搞一把基本英雄的創(chuàng)建作為背景

  • 英雄單位的基本類抽取抽象
  • 技能抽象
  • 英雄單位持有技能抽象單位,用以測試

coding

先聲明英雄單位的抽象類妆档,需要名字僻爽,類型和技能

public abstract class AbsHero {

    private IHeroSkill mSkill;

    private String mName;

    private String mType;

    public AbsHero(IHeroSkill skill, String name) {
        mSkill = skill;
        mName = name;
        mType = genType();
    }

    protected abstract String genType();

    public void test() {
        System.out.println("開始測試英雄[" + mType + "-" + mName + "] 釋放技能Q:" + mSkill.releaseSkill(IHeroSkill.CMD.Q) + ",釋放技能W:" + mSkill.releaseSkill(IHeroSkill.CMD.W) + ",釋放技能E:" + mSkill.releaseSkill(IHeroSkill.CMD.E) + ",釋放技能R:" + mSkill.releaseSkill(IHeroSkill.CMD.R));
    }
}


public interface IHeroSkill {

    enum CMD {
        Q, W, E, R
    }
    String releaseSkill(CMD cmd);
}

實(shí)現(xiàn)老亞索的技能創(chuàng)建和英雄子類

public class HappyMan extends AbsHero {

    public HappyMan(IHeroSkill skill) {
        super(skill, "亞索");
    }

    @Override
    protected String genType() {
        return "AD";
    }
}

public class HappyManSkill implements IHeroSkill{

    @Override
    public String releaseSkill(CMD cmd) {
        switch (cmd){
            case E:
                return "快樂就完事,問好也追不上我~";
            case Q:
                return "哈撒ki~";
            case R:
                return "Holy ye kei duo~";
            case W:
                return "風(fēng)墻~";
        }
        return "NOTHING";
    }
}

進(jìn)行測試:

AbsHero happyMan = new HappyMan(new HappyManSkill());
happyMan.test();
//開始測試英雄[AD-亞索] 釋放技能Q:哈撒ki~,釋放技能W:風(fēng)墻~,釋放技能E:快樂就完事贾惦,問好也追不上我~,釋放技能R:Holy ye kei duo~

可以看到我們的上層模塊對(duì)英雄的持有是抽象的,對(duì)于技能的實(shí)現(xiàn)也是通過依賴注入的方式傳遞給了英雄中敦捧,然后直接調(diào)用測試~

接下來我們創(chuàng)建個(gè)新英雄狗頭~

public class DogMan extends AbsHero {

    public DogMan(IHeroSkill skill) {
        super(skill, "狗頭");
    }

    @Override
    protected String genType() {
        return "AD-AP";
    }
}

public class DogManSkill implements IHeroSkill {
    @Override
    public String releaseSkill(CMD cmd) {
        switch (cmd){
            case E:
                return "畫個(gè)圈圈詛咒你~";
            case Q:
                return "專注發(fā)育疊被動(dòng)~";
            case R:
                return "變大须板,增強(qiáng)自身屬性";
            case W:
                return "惡心對(duì)面,降低對(duì)面雙抗兢卵,減速~";
        }
        return "NOTHING";
    }
}

AbsHero happyMan = new HappyMan(new HappyManSkill());
happyMan.test();
AbsHero goutou = new DogMan(new DogManSkill());
goutou.test();

//開始測試英雄[AD-亞索] 釋放技能Q:哈撒ki~,釋放技能W:風(fēng)墻~,釋放技能E:快樂就完事习瑰,問好也追不上我~,釋放技能R:Holy ye kei duo~
//開始測試英雄[AD-AP-狗頭] 釋放技能Q:專注發(fā)育疊被動(dòng)~,釋放技能W:惡心對(duì)面,降低對(duì)面雙抗秽荤,減速~,釋放技能E:畫個(gè)圈圈詛咒你~,釋放技能R:變大甜奄,增強(qiáng)自身屬性

可以看到很方便我們就能創(chuàng)建第二英雄,并且技能可以隨便配置窃款,如果想要削弱某個(gè)英雄或者重做某個(gè)英雄的技能课兄,直接更換已有的技能實(shí)現(xiàn)即可,我們的技能作為接口的方式給英雄來依賴晨继,既不會(huì)侵入后期技能創(chuàng)建的迭代烟阐,也不會(huì)影響今后技能的生產(chǎn),唯一可能帶來的問題就可能是接口方法會(huì)發(fā)生改動(dòng),這樣會(huì)直接導(dǎo)致實(shí)現(xiàn)者要發(fā)生變化蜒茄,其實(shí)就算如此也不必慌唉擂,這是語言特性所導(dǎo)致,我們完全可以通過一個(gè)抽象類來實(shí)現(xiàn)這個(gè)接口檀葛,默認(rèn)其他的技能創(chuàng)建者也都通過繼承這個(gè)抽象類即可玩祟,這樣就避免了今后就算接口改動(dòng)導(dǎo)致其他子類需要改動(dòng)的成本~

特點(diǎn)

這里還是把書里總結(jié)的貼來哈~

  • 抽象和實(shí)現(xiàn)分離:這也是橋梁模式的主要特點(diǎn),它完全是為了解決繼承的缺點(diǎn)而提出的設(shè)計(jì)模式屿聋。在該模式下空扎,實(shí)現(xiàn)可以不受抽象的約束,不用再綁定在一個(gè)固定的抽象層次上
  • 優(yōu)秀的擴(kuò)充能力:看看我們的例子胜臊,想增加實(shí)現(xiàn)勺卢?沒問題!想增加抽象象对,也沒有問題黑忱!只要對(duì)外暴露的接口層允許這樣的變化,我們已經(jīng)把變化的可能性減到最小
  • 實(shí)現(xiàn)細(xì)節(jié)對(duì)客戶透明:客戶不用關(guān)心細(xì)節(jié)的實(shí)現(xiàn)勒魔,它已經(jīng)由抽象層通過聚合關(guān)系完成了封裝

使用場景

  • 不希望或不適用使用繼承的場景:例如繼承層次過渡甫煞、無法更細(xì)化設(shè)計(jì)顆粒等場景,需要考慮使用橋梁模式
  • 接口或抽象類不穩(wěn)定的場景:明知道接口不穩(wěn)定還想通過實(shí)現(xiàn)或繼承來實(shí)現(xiàn)業(yè)務(wù)需求冠绢,那是得不償失的抚吠,也是比較失敗的做法
  • 重用性要求較高的場景:設(shè)計(jì)的顆粒度越細(xì),則被重用的可能性就越大弟胀,而采用繼承則受父類的限制楷力,不可能出現(xiàn)太細(xì)的顆粒度(這里需要補(bǔ)充一點(diǎn),粒度的粗細(xì)由開發(fā)者自己掌握孵户,不是越細(xì)越好萧朝,越細(xì)帶來的開發(fā)成本也會(huì)相對(duì)上升,所以對(duì)于粒度的掌握還是要根據(jù)項(xiàng)目的規(guī)模和個(gè)人的經(jīng)驗(yàn)來把握

總結(jié)

橋梁模式是非常簡單的夏哭,使用該模式時(shí)主要考慮如何拆分抽象和實(shí)現(xiàn)检柬,并不是一涉及繼承就要考慮使用該模式,那還要繼承干什么呢竖配?橋梁模式的意圖還是對(duì)變化的封裝何址,盡量把可能變化的因素封裝到最細(xì)、最小的邏輯單元中进胯,避免風(fēng)險(xiǎn)擴(kuò)散用爪。因此讀者在進(jìn)行系統(tǒng)設(shè)計(jì)時(shí),發(fā)現(xiàn)類的繼承有N層時(shí)龄减,可以考慮使用橋梁模式项钮。`認(rèn)為是系統(tǒng)中最容易重現(xiàn)變化的環(huán)節(jié)以接口的方式進(jìn)行依賴,粒度越細(xì)越好,粒度的把握參閱上述

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末烁巫,一起剝皮案震驚了整個(gè)濱河市署隘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亚隙,老刑警劉巖磁餐,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異阿弃,居然都是意外死亡诊霹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門渣淳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脾还,“玉大人,你說我怎么就攤上這事入愧”陕” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵棺蛛,是天一觀的道長怔蚌。 經(jīng)常有香客問我,道長旁赊,這世上最難降的妖魔是什么桦踊? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮终畅,結(jié)果婚禮上籍胯,老公的妹妹穿的比我還像新娘。我一直安慰自己离福,他們只是感情好芒炼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著术徊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲸湃。 梳的紋絲不亂的頭發(fā)上赠涮,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音暗挑,去河邊找鬼笋除。 笑死,一個(gè)胖子當(dāng)著我的面吹牛炸裆,可吹牛的內(nèi)容都是我干的垃它。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼国拇!你這毒婦竟也來了洛史?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤酱吝,失蹤者是張志新(化名)和其女友劉穎也殖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體务热,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忆嗜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崎岂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捆毫。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖冲甘,靈堂內(nèi)的尸體忽然破棺而出绩卤,到底是詐尸還是另有隱情,我是刑警寧澤损合,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布省艳,位于F島的核電站,受9級(jí)特大地震影響嫁审,放射性物質(zhì)發(fā)生泄漏跋炕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一律适、第九天 我趴在偏房一處隱蔽的房頂上張望辐烂。 院中可真熱鬧,春花似錦捂贿、人聲如沸纠修。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扣草。三九已至,卻和暖如春颜屠,著一層夾襖步出監(jiān)牢的瞬間辰妙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工甫窟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留密浑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓粗井,卻偏偏與公主長得像尔破,于是被迫代替她去往敵國和親街图。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359