天天看點

關于擴充卡模式,我遺漏了什麼

近期有些tasks需要 重構or适配 老的代碼。

與其向上面堆💩,不如優雅的去解決。

首先我的問題在于,錯誤的把 堆屎的操作 ,當作了擴充卡模式的操作。

比如原函數入參,需要更改某個屬性,把這種操作外包一層套進去,就是堆屎。

擴充卡模式的重點在于:擴充卡實作目标接口,并且持有适配者的執行個體

做法是:轉換一個接口到另一個接口。(這個經常和外觀模式搞混)

實際工作中嘗試使用虛方法去實作,讓前端的調用為被轉換過的接口。

虛方法:

1、virtual方法表示此方法可以被重寫, 也就是說這個方法具有多态.父類中的方法是通用方法,可以在子類中重寫以重新規定方法邏輯.

2、virtual方法可以直接使用,和普通方法一樣

3、不是必須重寫的. 子類可以使用base.方法 的方式調用, 無論有沒有在子類使用override去重寫

virtual關鍵字隻是明确标示此方法可以被重寫, 其實它和一般的方法沒有什麼差別

擴充卡模式分為類結構型模式和對象結構型模式兩種,前者類之間的耦合度比後者高,且要求程式員了解現有元件庫中的相關元件的内部結構,是以應用相對較少些。

但是我偏要用類擴充卡!

類擴充卡

類擴充卡:擴充卡繼承适配對象,并實作适配目标的所有方法

public interface EuropeSocket {
    /** 歐式三叉 通電 接通電 插座*/
    String useEuropesocket();
}

// 歐式三叉實作類
public class EuropeSocketImpl implements EuropeSocket {

    @Override
    public String useEuropesocket() {
        String msg ="使用歐式三叉充電";
        return msg;
    }
}
           
public interface ChineseSocket {
    /**
     * 使用中國雙叉充電
     * @return
     */
    String useChineseSocket();
}

// 中國插頭的實作類
public class ChineseSocketImpl implements ChineseSocket {

    @Override
    public String useChineseSocket() {
        String msg="使用中國雙叉充電";
        return msg;
    }
}
           
/**
 * 定義擴充卡類 中國雙叉轉為歐洲三叉
 *
 */
public class ChineseAdapterEurope extends EuropeSocketImpl implements ChineseSocket {

    @Override
    public String useChineseSocket() {
        System.out.println("使用轉換器轉換完成");
        return useEuropesocket();
    }
}
           

開始使用測試!

public class Computer {

    public String useChineseSocket(ChineseSocket chineseSocket) {
        if(chineseSocket == null) {
            throw new NullPointerException("sd card null");
        }
        return chineseSocket.useChineseSocket();
    }
}
           

提前注:父類聲明子類執行個體化産生的對象使用的是子類從父類繼承的方法和屬性。 

父類聲明子類執行個體化對象詳解_扶公瑾以蘇的部落格-CSDN部落格_c父類對象由子類執行個體化

public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        ChineseSocket chineseSocket = new ChineseSocketImpl();
        System.out.println(computer.useChineseSocket(chineseSocket));
        System.out.println("------------");
        ChineseAdapterEurope adapter = new ChineseAdapterEurope();
        System.out.println(computer.useChineseSocket(adapter));
        /**
         * 輸出:
         * 使用中國雙叉充電
         * ------------
         * 使用轉換器轉換完成
         * 使用歐式三叉充電
         */
    }
}
           

對象擴充卡

實作方式:對象擴充卡模式可釆用将現有元件庫中已經實作的元件引入擴充卡類中,該類同時實作目前系統的業務接口。

題目還是和上面一樣的哈。代碼其實差異很小

目标(Target)接口:即圖中的歐式三叉

public interface EuropeSocket {
    /** 歐式三叉 通電 接通電 插座*/
    String useEuropesocket();
}

// 歐式三叉實作類
public class EuropeSocketImpl implements EuropeSocket {

    @Override
    public String useEuropesocket() {
        String msg ="使用歐式三叉充電";
        return msg;
    }
}
複制代碼
           

适配者(Adaptee):即中國雙叉

public interface ChineseSocket {
    /**
     * 使用中國雙叉充電
     * @return
     */
    String useChineseSocket();
}

// 中國插頭的實作類
public class ChineseSocketImpl implements ChineseSocket {

    @Override
    public String useChineseSocket() {
        String msg="使用中國雙叉充電";
        return msg;
    }
}
複制代碼
           

擴充卡(Adapter)類: 就是這個擴充卡内做了一些更改 從繼承改為了成員變量的方式

public class ChineseAdapterEurope implements ChineseSocket {

    private EuropeSocket europeSocket;

    public ChineseAdapterEurope(EuropeSocket europeSocket) {
        this.europeSocket = europeSocket;
    }

    @Override
    public String useChineseSocket() {
        System.out.println("使用轉換器轉換完成");
        return europeSocket.useEuropesocket();
    }
}
複制代碼
           

電腦類

public class Computer {

    public String useChineseSocket(ChineseSocket chineseSocket) {
        if(chineseSocket == null) {
            throw new NullPointerException("sd card null");
        }
        return chineseSocket.useChineseSocket();
    }
}
複制代碼
           

測試:

public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        ChineseSocket chineseSocket = new ChineseSocketImpl();
        System.out.println(computer.useChineseSocket(chineseSocket));

        System.out.println("------------");
        //這裡做了更改
        EuropeSocket europeSocket=new EuropeSocketImpl();
        ChineseAdapterEurope adapter = new ChineseAdapterEurope(europeSocket);
        System.out.println(computer.useChineseSocket(adapter));
        /**
         * 輸出:
         * 使用中國雙叉充電
         * ------------
         * 使用轉換器轉換完成
         * 使用歐式三叉充電
         */
    }
}
           

适合于解決問題常見:

  •  需要的東西有,但不能用,且短時間無法改造。即,使得一個功能适合不同的環境。
  •   在開發中,系統的資料、行為都比對,但接口不符時,可以考慮擴充卡。
  •   希望複用一些現存的類,但是接口又與複用環境的要求不一緻,應該考慮用擴充卡模式。(使用一個已經存在的類,但它的接口(即,方法),與需要的不相同時)

2023/2/12

劃重點:希望複用一些現存的類,但是接口又與複用環境的要求不一緻,應該考慮用擴充卡模式。(使用一個已經存在的類,但它的接口(即,方法),與需要的不相同時)

這個正是我現在面臨的問題。

總之,時間足夠我就優雅的,完美的去建立一個可擴充性強的适配層。

如果催我。那我就堆堆樂 💩💩💩

references:

Java設計模式-擴充卡模式 理論代碼相結合 - 掘金

繼續閱讀