設計模式之旅12--橋接模式

weixin_34377065發表於2018-07-23

1. 定義

橋接模式也叫橋樑模式,通過抽象角色引用實現角色,將抽象和實現解耦,使得兩者可以獨立地變化。其中抽象和實現可以理解為兩個不同的維度。

2570030-143f633bcf6db3e7.png
橋接模式

2. 使用場景

  • 一個類存在兩個獨立變化的維度,並且兩個維度都需要擴充套件。
  • 不希望或不適用使用繼承的場景。
  • 介面或抽象類不穩定的場景,明知介面不穩定還想通過實現或繼承來實現業務需求,那是得不償失的。
  • 重用性要求較高的場景,設計的顆粒度越細,則被重用的可能性就越大,而採用繼承則受父類的限制,不可能出現太細的顆粒度。

3. 實現

這裡以衝咖啡為例子進行程式碼實現,實現大杯小杯、加糖不加糖兩個維度的搭配。

抽象化角色——咖啡:

/**
 * Abstraction是抽象化角色,保持實現化角色的引用
 * 這裡的Abstraction代表咖啡
 */
public abstract class Abstraction {

    //抽象化角色,保持實現化角色的引用,是橋接模式的核心
    //這裡的實現化角色代表咖啡的調料
    private Implementor mImplementor;

    public Abstraction(Implementor implementor) {
        mImplementor = implementor;
    }

    public Implementor getImplementor() {
        return mImplementor;
    }

    /**
     * 衝咖啡,具體實現由子類實現
     */
    public abstract void operator();

}

修正抽象化角色——大杯、小杯的咖啡:

/**
 * RefineAbstraction是修正抽象化角色,通過引用實現化角色Implementor對抽象化角色Abstraction進行修正
 * RefineAbstraction1是咖啡的實現類,代表大杯的咖啡
 */
public class RefineAbstraction1 extends Abstraction {

    public RefineAbstraction1(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operator() {
        System.out.println("大杯的" + this.getImplementor().implement() + "咖啡");
    }
}

public class RefineAbstraction2 extends Abstraction {

    public RefineAbstraction2(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operator() {
        System.out.println("小杯的" + this.getImplementor().implement() + "咖啡");
    }
}

實現化角色——調料:

/**
 * Implementor是實現化角色
 * 這裡代表咖啡的調料,具體調料由實現類實現
 */
public interface Implementor {

    String implement();

}

具體實現化角色——加糖、不加糖:

/**
 * ConcreteImplementor具體的實現化角色
 * ConcreteImplementor咖啡的調料的實現類,代表加糖
 * 
 */
public class ConcreteImplementor1 implements Implementor {
    @Override
    public String implement() {
        return "加糖";
    }
}

public class ConcreteImplementor2 implements Implementor {
    @Override
    public String implement() {
        return "不加糖";
    }
}

場景類:

public class Client {

    public static void main(String[] args) {

        Implementor i1 = new ConcreteImplementor1();//加糖
        Implementor i2 = new ConcreteImplementor1();//不加糖

        Abstraction a1 = new RefineAbstraction1(i1);//大杯、加糖
        Abstraction a2 = new RefineAbstraction1(i2);//大杯、不加糖
        Abstraction a3 = new RefineAbstraction2(i1);//小杯、加糖
        Abstraction a4 = new RefineAbstraction2(i2);//小杯、不加糖

        a1.operator();
        a2.operator();
        a3.operator();
        a4.operator();
    }

}

執行結果:

大杯的加糖咖啡
大杯的加糖咖啡
小杯的加糖咖啡
小杯的加糖咖啡

4. 優點

  • 抽象和實現分離。解決了繼承的缺點,橋接模式實現了不受抽象的約束,不用再繫結在一個固定的抽象層次上。
  • 優秀的擴充能力。抽象和實現都可以獨立擴充套件。
  • 實現細節對客戶透明。客戶不用關心細節的實現,它已經由抽象層通過聚合關係完成了封裝。

5. 缺點

  • 橋接模式的引入會增加系統的理解與設計難度。由於聚合關聯關係建立在抽象層,要求開發者針對抽象設計和程式設計。
  • 實際中不容易發現可以使用橋接模式的地方。橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍具有一定的侷限性。

相關文章