橋接設計模式 (Bridge)

1. 問題引出

實現某件產品,某產品有多種品牌(brand)和類型(kind)。
在這裏插入圖片描述
比較直觀的一種實現方式,多重繼承如下圖所示,多重繼承的兩大缺點:

  • 會導致有過多的類(類的數量=品牌數量*類型數量);
  • 新增品牌則需要新增所有的類型類,新增類型則需要新增所有的品牌類,違反了單一職責原則(單一職責原則:對類來說的,即一個類應該只負責一項職責。如類 A 負責兩個不同職責:職責 1,職責 2。當職責 1 需求變更 而改變 A 時,可能造成職責 2 執行錯誤,所以需要將類 A 的粒度分解爲 A1,A2)。
    在這裏插入圖片描述

2. 橋接模式解決問題

橋接模式中有4個角色:抽象化(Abstraction),改善後的抽象化(RefinedAbstraction),實現者(Implementor),具體實現者(ConcreteImplementor)。

  • 抽象化:類的功能層次結構最上層。
  • 改善後的抽象化:在抽象化角色基礎上增加了新功能的角色。
  • 實現者:定義了用於實現抽象化角色的接口的方法。
  • 具體實現者:負責實現實現者角色中定義的方法。

Product 的角色是抽象化,抽象化的實現 Brand1、Brand2、Brand3,實現者 Kind,具體的實現者 Kind1、Kind2、Kind3。
顯然使用橋接模式解決了上述的兩個缺點。
在這裏插入圖片描述

3. 代碼示例

Product.java, 抽象化角色 :

/**
 * 抽象化角色:類的功能層次結構最上層
 * @author syrdbt
 * @date 2020-02-25
 */
public abstract class Product {
    private Kind kind;

    public Product(Kind kind) {
        this.kind = kind;
    }

    public void make() {
        kind.make();
    }
}

Brand1.java:

/**
 * 改善後的抽象化角色
 * @author syrdbt
 * @date 2020-02-25
 */
public class Brand1 extends Product {

    public Brand1(Kind kind) {
        super(kind);
    }

    @Override
    public void make() {
        System.out.println("這個產品屬於 Brand1");
        super.make();
    }
}

Brand2.java:

/**
 * 改善後的抽象化角色
 * @author syrdbt
 * @date 2020-02-25
 */
public class Brand2 extends Product {

    public Brand2(Kind kind) {
        super(kind);
    }

    @Override
    public void make() {
        System.out.println("這個產品屬於 Brand2");
        super.make();
    }
}

Brand3.java:

/**
 * 改善後的抽象化角色
 * @author syrdbt
 * @date 2020-02-25
 */
public class Brand3 extends Product {

    public Brand3(Kind kind) {
        super(kind);
    }

    @Override
    public void make() {
        System.out.println("這個產品屬於 Brand3");
        super.make();
    }
}

Kind.java

/**
 * 實現者角色
 * @author syrdbt
 * @date 2020-02-25
 */
public interface Kind {
    void make();
}

Kind1.java

/**
 * 具體的實現者
 * @author syrdbt
 * @date 2020-02-25
 */
public class Kind1 implements Kind {

    @Override
    public void make() {
        System.out.println("製作 Kind1 類型的產品");
    }

}

Kind2.java:

/**
 * 具體的實現者
 * @author syrdbt
 * @date 2020-02-25
 */
public class Kind2 implements Kind{
    @Override
    public void make() {
        System.out.println("製作 Kind1 類型的產品");
    }
}

Kind3.java:

/**
 * 具體的實現者
 * @author syrdbt
 * @date 2020-02-25
 */
public class Kind3 implements Kind {
    @Override
    public void make() {
        System.out.println("製作 Kind3 類型的產品");
    }
}

測試類,BridgeMain.java:

/**
 * 測試類
 * @author syrdbt
 * @date 2020-02-25
 */
public class BridgeMain {
    public static void main(String[] args) {
        Product product = new Brand1(new Kind1());
        product.make();
    }
}

運行截圖:
在這裏插入圖片描述

參考文獻

  • 圖解設計模式 結城浩
  • 圖解設計模式 尚硅谷
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章