設(shè)計(jì)模式之橋接模式

一、簡介

橋接模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,假如一個(gè)類需要在多個(gè)維度擴(kuò)展,采用繼承方式會導(dǎo)致子類數(shù)量過多。這時(shí)候可以采用橋接模式,將各個(gè)變化部分分離,從而實(shí)現(xiàn)獨(dú)立變化互不干涉,但又在更高的抽象層實(shí)現(xiàn)組合以保證各子類能動態(tài)結(jié)合。

優(yōu)點(diǎn)在于降低了類與類之間的耦合,使得系統(tǒng)中類的個(gè)數(shù)更少,且系統(tǒng)擴(kuò)展更為方便。
缺點(diǎn)在于橋接模式的引入會增加系統(tǒng)的理解與設(shè)計(jì)難度。

橋接模式包含如下角色:
? Abstraction:?抽象類,除了定義了當(dāng)前維度的抽象以外,一般包含另一維度的實(shí)例(即實(shí)現(xiàn)類接口的引用),起橋梁作用,也就是可以使得抽象部分和實(shí)現(xiàn)部分的子類可以隨意組合(即兩維度的變化隨意組合)。
? RefinedAbstraction:?擴(kuò)充抽象類,繼承了Abstraction
? Implementor: ?實(shí)現(xiàn)類接口,定義了另一維度的抽象
? ConcreteImplementor:?具體實(shí)現(xiàn)類,定義了另一維度的各種具體變化的實(shí)現(xiàn)

橋接模式

二、使用場景

一個(gè)類需要在多維度擴(kuò)展,采用繼承方式會導(dǎo)致子類數(shù)量過多。這時(shí)候可以采用橋接模式,將抽象部分與實(shí)現(xiàn)部分分離,各部分可以獨(dú)立變化,降低了類與類之間的耦合,使得系統(tǒng)中類的個(gè)數(shù)更少,且系統(tǒng)擴(kuò)展更為方便。

也就是說將一個(gè)需要多維度變化的類拆分成抽象部分和實(shí)現(xiàn)部分,并且在抽象層對兩者做組合關(guān)聯(lián),用組合的方式來解決繼承的問題。舉個(gè)例子,如果一個(gè)類在兩個(gè)維度分別有m和n種變化,采用繼承的方式就需要擴(kuò)展出m*n個(gè)子類,且一個(gè)維度每增加一種變化就多出另一個(gè)維度變化總數(shù)的子類;如果將兩個(gè)維度拆分再組合,加起來也只有m+n個(gè)子類,且每個(gè)維度獨(dú)立擴(kuò)展,一個(gè)維度增加一種變化只需要增加1個(gè)子類。

三、舉例

/*
 * 以小攤販賣的早餐為例,我們從兩個(gè)維度分析,主食材有面條和煎餅等,輔助食材有雞蛋和肉絲等
 * 我們把主食材作為抽象部分,輔助食材作為實(shí)現(xiàn)部分
 */
public class 橋接模式 {
    public static void main(String[] args) {
        MajorFood food1=new Noodle1(new Meat());
        System.out.println(food1.getFood()+",共花費(fèi):"+food1.getCost());
        MajorFood food2=new Pancake(new Egg());
        System.out.println(food2.getFood()+",共花費(fèi):"+food2.getCost());
    }
}
//先看實(shí)現(xiàn)部分
//首先定義實(shí)現(xiàn)類接口,一個(gè)維度
interface MinorFood{
    String getDesc();
    float getPrice();
}
//定義具體的實(shí)現(xiàn)類-雞蛋
class Egg implements MinorFood{
    @Override
    public String getDesc() {
        return "雞蛋";
    }
    @Override
    public float getPrice() {
        return 1;
    }
}
//定義具體的實(shí)現(xiàn)類-肉絲
class Meat implements MinorFood{
    @Override
    public String getDesc() {
        return "肉絲";
    }
    @Override
    public float getPrice() {
        return 1.5f;
    }
}
//再看抽象部分,作用類似于橋接模式中的橋,將兩個(gè)維度連接在一起
//定義抽象類(另一個(gè)維度),類中包含一個(gè)實(shí)現(xiàn)部分接口的引用,這樣抽象部分和實(shí)現(xiàn)部分的子類可以隨意組合
abstract class MajorFood{
    protected MinorFood minorFood;//實(shí)現(xiàn)部分實(shí)例
    public MajorFood(MinorFood minorFood){//橋接模式的關(guān)鍵,組合實(shí)現(xiàn)和抽象
        this.minorFood=minorFood;
    }
    public abstract String getFood();
    public abstract float getCost();
}
//定義擴(kuò)充抽象類-煎餅
class Pancake extends MajorFood{
    public Pancake(MinorFood minorFood){
        super(minorFood);
    }
    public String getFood(){
        return "恭喜,獲得一份煎餅+"+super.minorFood.getDesc();
    }
    public float getCost(){
        return 6+super.minorFood.getPrice();
    }
}
//定義擴(kuò)充抽象類-面條
class Noodle1 extends MajorFood{
    public Noodle1(MinorFood minorFood){
        super(minorFood);
    }
    public String getFood(){
        return "恭喜,獲得一份煮面+"+super.minorFood.getDesc();
    }
    public float getCost(){
        return 8+super.minorFood.getPrice();
    }
}   

結(jié)果

恭喜,獲得一份煮面+肉絲,共花費(fèi):9.5
恭喜,獲得一份煎餅+雞蛋,共花費(fèi):7.0

四、參考

橋接模式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容