• <menu id="gyiem"><menu id="gyiem"></menu></menu>
  • <menu id="gyiem"><code id="gyiem"></code></menu>

    Java設計模式(九) 橋接模式

    原創文章,轉載請務必將下面這段話置于文章開頭處(保留超鏈接)。
    本文轉發自技術世界原文鏈接 http://www.luozeyang.com/design_pattern/bridge/

    橋接模式定義

    橋接模式(Bridge Pattern),將抽象部分與它的實現部分分離,使它們都可以獨立地變化。更容易理解的表述是:實現系統可從多種維度分類,橋接模式將各維度抽象出來,各維度獨立變化,之后可通過聚合,將各維度組合起來,減少了各維度間的耦合。

    例講橋接模式

    不必要的繼承導致類爆炸

    汽車可按品牌分(本例中只考慮BMT,BenZ,Land Rover),也可按手動檔、自動檔、手自一體來分。如果對于每一種車都實現一個具體類,則一共要實現3*3=9個類。

    使用繼承方式的類圖如下
    Bridge pattern inherit class diagram

    從上圖可以看到,對于每種組合都需要創建一個具體類,如果有N個維度,每個維度有M種變化,則需要$M^N$個具體類,類非常多,并且非常多的重復功能。

    如果某一維度,如Transmission多一種可能,比如手自一體檔(AMT),則需要增加3個類,BMWAMT,BenZAMT,LandRoverAMT。

    橋接模式類圖

    橋接模式類圖如下
    Bridge pattern class diagram

    從上圖可知,當把每個維度拆分開來,只需要M*N個類,并且由于每個維度獨立變化,基本不會出現重復代碼。

    此時如果增加手自一體檔,只需要增加一個AMT類即可

    橋接模式實例解析

    本文代碼可從作者Github下載

    抽象車

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package com.jasongj.brand;

    import com.jasongj.transmission.Transmission;

    public abstract class AbstractCar {

    protected Transmission gear;

    public abstract void run();

    public void setTransmission(Transmission gear) {
    this.gear = gear;
    }

    }

    按品牌分,BMW牌車

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.jasongj.brand;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class BMWCar extends AbstractCar{

    private static final Logger LOG = LoggerFactory.getLogger(BMWCar.class);

    @Override
    public void run() {
    gear.gear();
    LOG.info("BMW is running");
    };

    }

    BenZCar

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.jasongj.brand;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class BenZCar extends AbstractCar{

    private static final Logger LOG = LoggerFactory.getLogger(BenZCar.class);

    @Override
    public void run() {
    gear.gear();
    LOG.info("BenZCar is running");
    };

    }

    LandRoverCar

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.jasongj.brand;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class LandRoverCar extends AbstractCar{

    private static final Logger LOG = LoggerFactory.getLogger(LandRoverCar.class);

    @Override
    public void run() {
    gear.gear();
    LOG.info("LandRoverCar is running");
    };

    }

    抽象變速器

    1
    2
    3
    4
    5
    6
    7
    package com.jasongj.transmission;

    public abstract class Transmission{

    public abstract void gear();

    }

    手動檔

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.jasongj.transmission;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class Manual extends Transmission {

    private static final Logger LOG = LoggerFactory.getLogger(Manual.class);

    @Override
    public void gear() {
    LOG.info("Manual transmission");
    }
    }

    自動檔

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.jasongj.transmission;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class Auto extends Transmission {

    private static final Logger LOG = LoggerFactory.getLogger(Auto.class);

    @Override
    public void gear() {
    LOG.info("Auto transmission");
    }
    }

    有了變速器和品牌兩個維度各自的實現后,可以通過聚合,實現不同品牌不同變速器的車,如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.jasongj.client;

    import com.jasongj.brand.AbstractCar;
    import com.jasongj.brand.BMWCar;
    import com.jasongj.brand.BenZCar;
    import com.jasongj.transmission.Auto;
    import com.jasongj.transmission.Manual;
    import com.jasongj.transmission.Transmission;

    public class BridgeClient {

    public static void main(String[] args) {
    Transmission auto = new Auto();
    AbstractCar bmw = new BMWCar();
    bmw.setTransmission(auto);
    bmw.run();


    Transmission manual = new Manual();
    AbstractCar benz = new BenZCar();
    benz.setTransmission(manual);
    benz.run();
    }

    }

    橋接模式與OOP原則

    已遵循的原則

    • 依賴倒置原則
    • 迪米特法則
    • 里氏替換原則
    • 接口隔離原則
    • 單一職責原則
    • 開閉原則

    未遵循的原則

    • NA

    Java設計模式系列

    郭俊 Jason wechat
    歡迎關注作者微信公眾號【大數據架構】
    您的贊賞將支持作者繼續原創分享
    速赢彩app 沧州 | 丽水 | 神农架 | 海西 | 安康 | 克孜勒苏 | 天水 | 定西 | 琼中 | 平潭 | 德州 | 阿拉善盟 | 馆陶 | 广汉 | 荆州 | 眉山 | 金坛 | 安庆 | 凉山 | 阿坝 | 邢台 | 淄博 | 克孜勒苏 | 梅州 | 绍兴 | 肥城 | 醴陵 | 陕西西安 | 塔城 | 湖南长沙 | 许昌 | 和田 | 随州 | 赵县 | 德清 | 延边 | 衢州 | 镇江 | 平凉 | 安徽合肥 | 防城港 | 运城 | 襄阳 | 姜堰 | 常德 | 如皋 | 霍邱 | 诸城 | 汉川 | 燕郊 | 北海 | 咸宁 | 驻马店 | 诸暨 | 南充 | 黑龙江哈尔滨 | 昌吉 | 毕节 | 内江 | 台北 | 惠东 | 黄石 | 平凉 | 三沙 | 乳山 | 博尔塔拉 | 玉环 | 黔东南 | 盘锦 | 灌南 | 迁安市 | 嘉峪关 | 天水 | 黄南 | 潍坊 | 宜都 | 深圳 | 德宏 | 山东青岛 | 塔城 | 朝阳 | 唐山 | 乐平 | 淮安 | 果洛 | 定安 | 周口 | 许昌 | 朝阳 | 那曲 | 乐平 | 渭南 | 嘉峪关 | 安顺 | 林芝 | 柳州 | 建湖 | 龙口 | 荆州 | 雅安 | 南平 | 乐山 | 桂林 | 延边 | 榆林 | 义乌 | 柳州 | 吉林长春 | 张掖 | 安康 | 湖北武汉 | 湘西 | 宜宾 |