橋接模式:探索JDBC底層實現

1、目錄概要

設計模式2

2、問題探究

需求:假設要設計一個電腦商場管理系統的某個模塊設計,電腦分爲品牌和類型兩個緯度,咱們應該怎麼解決?html

按照初學者的思路,利用繼承就能簡單粗暴的實現,那咱們來看下這種思路的設計類圖。
設計模式2設計模式

從電腦緯度劃分微信

package com.aaron.bridge;

public interface Computer {
    public void sale();
}

class Desktop implements Computer{
    @Override
    public void sale() {
        System.out.println("臺式電腦");
    }
}

class Laptop implements Computer{
    @Override
    public void sale() {
        System.out.println("筆記本電腦");
    }
}

class Pad implements Computer{
    @Override
    public void sale() {
        System.out.println("平板電腦");
    }
}

從品牌緯度劃分ide

package com.aaron.bridge;
// 宏碁品牌的三種類型
public class AcerDesktop extends Desktop{
    @Override
    public void sale() {
        System.out.println("宏碁臺式機");
    }
}

class AcerLaptop extends Laptop{
    @Override
    public void sale() {
        System.out.println("宏碁筆記本電腦");
    }
}

class AcerPad extends Pad{
    @Override
    public void sale() {
        System.out.println("宏碁平板電腦");
    }
}
package com.aaron.bridge;

// 蘋果品牌的三種類型
public class AppleDesktop extends Desktop{
    @Override
    public void sale() {
        System.out.println("蘋果臺式機");
    }
}

class AppleLaptop extends Laptop{
    @Override
    public void sale() {
        System.out.println("蘋果筆記本電腦");
    }
}

class ApplePad extends Pad{
    @Override
    public void sale() {
        System.out.println("蘋果平板電腦");
    }
}
package com.aaron.bridge;

//戴爾品牌的三種類型
public class DellDesktop extends Desktop{
    @Override
    public void sale() {
        System.out.println("戴爾臺式機");
    }
}

class DellLaptop extends Laptop{
    @Override
    public void sale() {
        System.out.println("戴爾筆記本電腦");
    }
}

class DellPad extends Pad{
    @Override
    public void sale() {
        System.out.println("戴爾平板電腦");
    }
}

問題1:假設咱們的系統按照上述思路設計,當咱們新增一個品牌的時候,怎麼辦?函數

根據上述思路,從品牌緯度擴展品牌時直接新增臺式機、筆記本電腦、平板電腦的類便可。this

問題2:當咱們新增一個機器類型的時候又該怎麼辦?
根據上述思路,在機器緯度類型擴展。設計

  1. 添加新的電腦機型。
  2. 在全部的品牌中,都新增新的機型。
package com.aaron.bridge;

// 電腦緯度
public interface Computer {
    public void sale();
}

class Desktop implements Computer{
    @Override
    public void sale() {
        System.out.println("臺式電腦");
    }
}

class Laptop implements Computer{
    @Override
    public void sale() {
        System.out.println("筆記本電腦");
    }
}

class Pad implements Computer{
    @Override
    public void sale() {
        System.out.println("平板電腦");
    }
}

class MaxPad implements Computer{
    @Override
    public void sale() {
        System.out.println("超大屏電腦");
    }
}

// 品牌緯度
public class DellDesktop extends Desktop{
    @Override
    public void sale() {
        System.out.println("戴爾臺式機");
    }
}

class DellLaptop extends Laptop{
    @Override
    public void sale() {
        System.out.println("戴爾筆記本電腦");
    }
}

class DellPad extends Pad{
    @Override
    public void sale() {
        System.out.println("戴爾平板電腦");
    }
}

class DellPad extends Pad{
    @Override
    public void sale() {
        System.out.println("戴爾平板電腦");
    }
}

class DellMaxPad extends Pad{
    @Override
    public void sale() {
        System.out.println("超大屏平板電腦");
    }
}

思考:當咱們添加少許的機型和品牌的時候,該方案的代碼擴展性仍是能夠接受的。可是,再往遠思考一步。code

  1. 假設電腦商城,添加10個品牌,再添加10種機型,怎麼辦?
  2. 系統已經上線,系統處於維護階段人力有限,怎麼辦?

問題:上述問題主要是把電腦和品牌兩個緯度耦合。htm

  1. 違背單一職責原則(一個類只由一個維度影響)
  2. 違背開閉原則(對拓展開放,對修改關閉)。

解決:將機器、品牌兩個緯度進行拆分,不要將他們耦合。對象

3、解決思路

3.1 什麼是橋接模式?

將兩個維度(抽象、實現)分離,使它們均可以獨立地變化。

3.2 橋接模式的分析
  1. 類型:臺式機、筆記本電腦、平板電腦。
  2. 品牌:宏碁、蘋果、戴爾。

關鍵:將上述問題拆分紅兩個緯度類型和品牌。咱們剛剛也討論了,主要解決拓展性問題。當添加一個新的機器類型或者品牌的時候,不會對其餘機器類型或者品牌產生影響。

概念:簡單談下概念,重點根據類圖和實現代碼去理解Abstraction、RefinedAbstraction、Implementor、ConcreteImplementor

Abstraction:抽象部分的接口。一般在這個對象裏面,要維護一個實現部分的對象引用,在抽象對象裏面的方法,須要調用實現部分的對象來完成。這個對象裏面的方法,一般都是跟具體的業務相關的方法。

RefinedAbstraction:
擴展抽象部分的接口,一般在這些對象裏面,定義跟實際業務相關的方法,這些方法的實現一般會使用Abstraction中定義的方法,也可能須要調用實現部分的對象來完成。

Implementor:
定義實現部分的接口,這個接口不用和Abstraction裏面的方法一致(根據約定優於配置原則,建議跟Abstraction一致。),一般是由Implementor接口提供基本的操做,而Abstraction裏面定義的是基於這些基本操做的業務方法,也就是說Abstraction定義了基於這些基本操做的較高層次的操做。

ConcreteImplementor:
真正實現Implementor接口的對象。

設計模式2

3.3 橋接模式實現

一、實體部分設計

package com.aaron.bridge;

/**
 * 
 * @author xiaoyongAaron
 * 品牌緯度-實現部分接口
 */
public interface ImplementorBrand {
    public void sale();
}

class  ConcreteImplementorAcer implements ImplementorBrand{

    @Override
    public void sale() {
        System.out.println("宏碁品牌");
    }
}

class ConcreteImplementorApple implements ImplementorBrand{
    @Override
    public void sale() {
        System.out.println("蘋果品牌");
    }
}

class ConcreteImplementorDell implements ImplementorBrand{
    @Override
    public void sale() {
        System.out.println("戴爾品牌");        
    }
}

二、抽象部分設計

package com.aaron.bridge;

/**
 * 機器類型緯度-抽象部分
 * @author xiaoyongAaron
 */
public class AbstractionComputer {
     protected ImplementorBrand brand;
          
     public AbstractionComputer(ImplementorBrand brand){
         this.brand=brand;
     }
     
     public void sale(){
        brand.sale(); 
     };

}

/**
 * 擴展部分
 * @author xiaoyongAaron
 */
class RefinedAbstractionDesktop extends AbstractionComputer{
    public RefinedAbstractionDesktop(ImplementorBrand brand) {
        super(brand);
    }

    @Override
    public void sale() {
        //添加本身的特性,實際業務。
        paly();
        super.sale();
    }
    
    public void paly(){
        System.out.println("我臺式機抗摔打");
    }
}

class RefinedAbstractionLaptop extends AbstractionComputer{
    public RefinedAbstractionLaptop(ImplementorBrand brand) {
        super(brand);
    }

    @Override
    public void sale() {
        //添加本身的特性,實際業務。
        lighting();
        super.sale();
    }
    
    public void lighting(){
        System.out.println("我筆記本電腦充電5分鐘,續航5小時");
    }
}

class RefinedAbstractionPad extends AbstractionComputer{
    public RefinedAbstractionPad(ImplementorBrand brand) {
        super(brand);
    }

    @Override
    public void sale() {
        //添加本身的特性,實際業務。
        weighting();
        super.sale();
    }
    
    public void weighting(){
        System.out.println("我平板電腦便於攜帶");
    }
}

四、執行結果顯示

設計模式2

4、問題回顧

4.1 什麼是橋接模式、爲何要橋接?

簡單說橋接模式就是把兩個緯度分離,因此說當咱們在實際開發的時候,遇到兩個維度問題的時候,直接條件反射橋接模式。

就像上述問題,當有兩個維度(品牌+機器類型)賦予給一個類的時候,基於單一職責原則,須要把它們解耦。那經過上述範例可知,那麼咱們就須要一座橋同樣,把兩個緯度用一箇中間物(類或者接口)把它們關聯起來,從而達到咱們的目的。

4.2 橋接模式怎麼接?

核心:如何把Implementor對象傳遞到抽象接口。

  1. 如上述描述,利用構造函數傳參。
  2. 創造無參構造函數,添加get、set方法。
  3. 工廠模式:參考設計模式的工廠模式。
  4. IOC控制反轉,最經典的就是Spring容器。內部的實現原理本來建立對象都是由咱們本身管理,可是把這一步驟交給容器管理,就不用咱們擔憂了。例如在JDBC的設計當中,充當這個角色的就是DriverManage去把對象注入在抽象接口當中。
4.3 橋接模式本質和經驗
  1. 本質:抽象與實現(兩個緯度)分離。
  2. 多用對象組合(has-A),少用繼承。
  3. 開閉原則:咱們應該對代碼拓展開放,拒絕代碼修改。

實際應用場景:
設計模式2

做者:碼農皮邱
原文:https://www.cnblogs.com/qiuyong/p/11107180.html
推薦:您的支持是對博主深刻思考總結的最大鼓勵,要是有須要關注公衆號與做者面對面對話交流~
說明:本文版權歸做者全部,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接,尊重做者的勞動成果。

微信公衆號

相關文章
相關標籤/搜索