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();
}
}
運行截圖:
參考文獻
- 圖解設計模式 結城浩
- 圖解設計模式 尚硅谷