軟體設計模式白話文系列(八)橋接模式

2022-11-13 21:03:21

軟體設計模式白話文系列(八)橋接模式

1、描述

把一個事物的多個維度剝離出來,通過組合方式來達到靈活設計的目的,Java 中,我們一般是通過物件參照來替換繼承關係,從而將抽象和實現解耦合。

橋接模式,可能大家只是不瞭解這個名稱,但是我們的實際開發習慣基本都是有使用的。例如 spring 的注入功能(別說沒用過哈)。所以說學習優秀的框架,就算沒有去熟悉它的原始碼,精通它的底層邏輯,僅僅只是簡單的使用都會在潛意識下提高我們的程式碼水平。

2、模式結構與實現邏輯

  • 抽象化類:業務抽象類。參照不同維度的介面物件。在日常開發中我們習慣忽略這個類,改進為業務介面類,需參照的介面物件直接在擴充套件抽象化類直接參照。
  • 擴充套件抽象化類:抽象化類的子類,就是日常開發中的業務實現類。
  • 實現化類:維度介面類,一般有多個,一個事物維度對一個該類。
  • 具體實現化類:實現化類的實現類。

本質的實現方式就是:業務類(擴充套件抽象化類)中參照其餘業務類的父類別或者介面(實現化類),在構造業務類時,根據需求動態傳入其餘業務類的具體實現類(具體實現類)。

3、實戰程式碼

實戰事例說明:

模擬購買私有數位憑證業務,私有數位憑證分為 RootCA 證書、SubCA 證書、訂戶證書 三類,購買方式分為支付寶支付、微信支付兩種。如果業務實現類通過繼承或者實現介面方式來實現邏輯,就不考慮還有其他業務情況,就只是滿足每種支付支付方式和每種證書型別建立就只少需要 6 個實現類來完成目標,顯然這樣會導致系統暴增。然後我們通過橋接模式只需要一個類就解決了。

/**
 * 實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-13 00:01:54
 */
public interface PayService {
    void pay();
}

/**
 * 實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:58:24
 */
public interface CertService {
    void createCert();
}

/**
 * 抽象化類
 * 日常開發中一般沒有抽象出這個類的
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:41:04
 */
public abstract class BuyService {
    protected PayService payService;
    protected CertService certService;

    public BuyService(PayService payService, CertService certService) {
        this.payService = payService;
        this.certService = certService;
    }

    public abstract void BuyCert();
}

/**
 * 具體實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-13 00:01:54
 */
public class AlipayServiceImpl implements PayService {
    @Override
    public void pay() {
        System.out.print("支付寶支付金額,開始");
    }
}

/**
 * 具體實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-13 00:01:54
 */
public class WeChatServiceImpl implements PayService {
    @Override
    public void pay() {
        System.out.print("微信支付金額,開始");
    }
}

/**
 * 具體實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:59:44
 */
public class RootCAServiceImpl implements CertService{
    @Override
    public void createCert() {
        System.out.println("建立 RootCA 證書");
    }
}

/**
 * 具體實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:59:44
 */
public class SubCAServiceImpl implements CertService{
    @Override
    public void createCert() {
        System.out.println("建立 SubCA 證書");
    }
}

/**
 * 具體實現化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:59:44
 */
public class CertServiceImpl implements CertService {
    @Override
    public void createCert() {
        System.out.println("建立訂戶證書");
    }
}

/**
 * 擴充套件抽象化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:41:04
 */
public class BuyServiceImpl extends BuyService {

    public BuyServiceImpl(PayService payService, CertService certService) {
        super(payService, certService);
    }

    @Override
    public void BuyCert() {
        payService.pay();
        certService.createCert();
    }
}

/**
 * 測試類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-13 00:10:43
 */
public class Client {
    public static void main(String[] args) {
        BuyService buyService = new BuyServiceImpl(new AlipayServiceImpl(), new RootCAServiceImpl());
        buyService.BuyCert();
        System.out.println("------------------------");

        BuyService buyService2 = new BuyServiceImpl(new WeChatServiceImpl(), new RootCAServiceImpl());
        buyService2.BuyCert();
        System.out.println("------------------------");

        BuyService buyService3 = new BuyServiceImpl(new WeChatServiceImpl(), new SubCAServiceImpl());
        buyService3.BuyCert();
        System.out.println("------------------------");

        BuyService buyService4 = new BuyServiceImpl(new AlipayServiceImpl(), new SubCAServiceImpl());
        buyService4.BuyCert();
        System.out.println("------------------------");

        BuyService buyService5 = new BuyServiceImpl(new WeChatServiceImpl(), new CertServiceImpl());
        buyService5.BuyCert();
        System.out.println("------------------------");

        BuyService buyService6 = new BuyServiceImpl(new AlipayServiceImpl(), new CertServiceImpl());
        buyService6.BuyCert();
        System.out.println("------------------------");
    }
}

執行結果:

4、日常開發習慣程式碼

作者平時開發程式碼時,是沒有 BuyService 這個抽象類的,在平時開發中每個業務類都是先定義介面類,再進行實現,如果為了規範實現化類而抽象化出抽象類,會顯得程式碼太過臃腫。

作者一般是結合 lombok 的 @AllArgsConstructor 來實現目的

/**
 * 抽象化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:41:04
 */
public interface BuyService {

    public abstract void BuyCert();
}

/**
 * 擴充套件抽象化類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-12 23:41:04
 */
@AllArgsConstructor
public class BuyServiceImpl implements BuyService {
    private PayService payService;
    private CertService certService;

    @Override
    public void BuyCert() {
        payService.pay();
        certService.createCert();
    }
}

/**
 * 測試類
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-13 00:10:43
 */
public class Client {
    public static void main(String[] args) {
        BuyService buyService = new BuyServiceImpl(new AlipayServiceImpl(), new RootCAServiceImpl());
        buyService.BuyCert();
        System.out.println("------------------------");

        BuyService buyService2 = new BuyServiceImpl(new WeChatServiceImpl(), new RootCAServiceImpl());
        buyService2.BuyCert();
        System.out.println("------------------------");

        BuyService buyService3 = new BuyServiceImpl(new WeChatServiceImpl(), new SubCAServiceImpl());
        buyService3.BuyCert();
        System.out.println("------------------------");

        BuyService buyService4 = new BuyServiceImpl(new AlipayServiceImpl(), new SubCAServiceImpl());
        buyService4.BuyCert();
        System.out.println("------------------------");

        BuyService buyService5 = new BuyServiceImpl(new WeChatServiceImpl(), new CertServiceImpl());
        buyService5.BuyCert();
        System.out.println("------------------------");

        BuyService buyService6 = new BuyServiceImpl(new AlipayServiceImpl(), new CertServiceImpl());
        buyService6.BuyCert();
        System.out.println("------------------------");
    }
}

5、適用性

  • 當一個業務存在多個維度且維度會獨立變化的時候。
  • 業務不希望使用繼承或因為多層次繼承而導致系統類暴增時。