【設計模式】Java設計模式 - 介面卡模式

語言: CN / TW / HK

【設計模式】Java設計模式 - 介面卡模式

:smile: 不斷學習才是王道

:fire: 繼續踏上學習之路,學之分享筆記

:facepunch: 總有一天我也能像各位大佬一樣

:trophy:原創作品,更多關注我CSDN: 一個有夢有戲的人

:facepunch:準備將部落格園、CSDN一起記錄分享自己的學習心得!!!

:full_moon_with_face:分享學習心得,歡迎指正,大家一起學習成長!

今天的內容有點多,也要努力學完!

目錄

  • 【設計模式】Java設計模式 - 介面卡模式

簡介

介面卡模式(Adapter Pattern)是作為兩個不相容的介面之間的橋樑。這種型別的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。就像電腦/投影儀那種,電腦要通過接線的方式投影,但是在以前的介面都是VGA介面,然而我們的電腦卻大多都是HDMI型別的,這就需要轉接頭來轉換介面,於是,這個轉接頭就充當著介面卡的身份。

介面卡模式分為:類介面卡模式、物件介面卡模式、介面介面卡模式

1、類介面卡模式

本次實驗使用手機充電的電壓轉換為例,其實就是這樣的,通過介面卡去繼承被適配者,並且實現目標介面。

整體如下:

①、被適配者

手機不能直接使用工作電壓充電,因此需要把工作電壓降壓到能提供手機充電的電壓,這裡先準備好一個工作電壓類,輸出220V標準工作電壓。

package com.lyd.demo.classadapter;
/**
 * @Author: lyd
 * @Description: 類介面卡 - 工作電壓:220V
 * @Date: 2022-08-27
 */
public class WorkingVoltage {
    public int outputWorkingPower() {
        int otp = 220; // 工作電壓輸出220V
        System.out.println("工作電壓輸出[" + otp + "]V");
        return otp;
    }
}

②、充電電壓介面

提供一個獲取充電電壓的介面,提供給介面卡實現。

package com.lyd.demo.classadapter;
/**
 * @Author: lyd
 * @Description: 類介面卡 - 充電器的電壓
 * @Date: 2022-08-27
 */
public interface IChargingVoltage {
    public int outputChangingPower();
}

③、介面卡

在實現充電電壓類的方法中進行電壓轉換。

package com.lyd.demo.classadapter.adapter;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.WorkingVoltage;
/**
 * @Author: lyd
 * @Description: 充電介面卡
 * @Date: 2022-08-27
 */
public class ChargingAdapter extends WorkingVoltage implements IChargingVoltage {
    public int outputChangingPower() {
        int workPower = outputWorkingPower(); // 獲得工作電壓
        int changingPower = workPower / 44; // 充電電壓
        System.out.println("經過介面卡降壓到[" + changingPower + "]V");
        return changingPower;
    }
}

④、例項

通過介面卡實現的介面方法去獲得到修改的資料,原理很簡單,就是可以理解為繼承第一個類獲取其屬性資料,在通過實現介面方法去修改。在類介面卡,能達到期望結果,java是單繼承,就是他需要去繼承類,這是他的缺點。

測試類

package com.lyd.demo.classadapter.test;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.adapter.ChargingAdapter;
/**
 * @Author: lyd
 * @Description: 測試類介面卡
 * @Date: 2022-08-27
 */
public class ClassAdapterTest {
    public static void main(String[] args) {IChargingVoltage chargingVoltage = new ChargingAdapter();
        System.out.println("轉換後的電壓:" + chargingVoltage.outputChangingPower());
    }
}

執行結果

2、物件介面卡模式

由於類介面卡需要繼承,並不是很好,因此,可以使用不繼承的方式,就是需要在介面卡中獲取被適配者的物件。根據合成複用原則,使用組合代替繼承。

①、介面卡類

其他類無需改動,只要將介面卡類的繼承方式改成不繼承的方式。

採用構造器初始化物件來獲得物件。

package com.lyd.demo.objectadapter.adapter;
import com.lyd.demo.classadapter.IChargingVoltage;
import com.lyd.demo.classadapter.WorkingVoltage;
/**
 * @Author: lyd
 * @Description: 充電介面卡
 * @Date: 2022-08-27
 */
public class ChargingAdapter implements IChargingVoltage {
    private WorkingVoltage workingVoltage;
    public ChargingAdapter(WorkingVoltage workingVoltage) {
        this.workingVoltage = workingVoltage;
    }
    public int outputChangingPower() {
        if (workingVoltage != null) {
            int workPower = workingVoltage.outputWorkingPower();
            // 獲得工作電壓
            int changingPower = workPower / 44; // 充電電壓
            System.out.println("經過介面卡降壓到[" + changingPower + "]V");
            return changingPower;
        }
        return 0;
    }
}

②、例項

測試的時候只需要將new例項化物件帶進去即可

public static void main(String[] args) {
    ChargingAdapter chargingAdapter = new ChargingAdapter(new WorkingVoltage());
    System.out.println("轉換後的電壓:" + chargingAdapter.outputChangingPower());
}

執行結果

物件適配模式與類適配模式基本上是一樣的,就只是將類適配模式的繼承方式改編成通過構造方法去獲取物件,使得以更加靈活。

3、介面介面卡

不需要實現所有方法,只想實現其中某個方法,可以設計一個抽象介面,並且讓他實現所有介面的空方法,即不需要寫方法體。

①、例1

例如:

定義一個接口裡麵包含幾個未實現的方法

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 介面
 * @Date: 2022-08-27
 */
public interface Interfaces {
    public void show1();
    public void show2();
    public void show3();
    public void show4();
}

定義抽象介面,並且實現空方法

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 介面卡,預設實現空方法,這樣呼叫介面卡的時候就可以根據自己想要的方法去重寫了
 * @Date: 2022-08-27
 */
public abstract class InterfacesAdapter implements Interfaces {
    public void show1() {
        System.out.println("abs show 1");
    }
    public void show2() {
        System.out.println("abs show 2");
    }
    public void show3() {
        System.out.println("abs show 3");
    }
    public void show4() {
        System.out.println("abs show 4");
    }
}

使用的時候根據自己需要去實現

通過例項化介面卡,在其中去重寫方法,呼叫的時候會使用重寫的方法,如果沒有重寫就是呼叫父類的方法。

package com.lyd.demo.interfaceadapter;
/**
 * @Author: lyd
 * @Description: 介面介面卡測試
 * @Date: 2022-08-27
 */
public class Main {
    public static void main(String[] args) {
        InterfacesAdapter adapter = new InterfacesAdapter() {
            @Override
            public void show1() { // 只重寫一個方法
                System.out.println("adapter show 1");
            }
        };
        adapter.show1();
        adapter.show3(); // 呼叫的時候就是抽象類的空方法
    }
}

執行結果

②、例2

本例詳情可以看菜鳥教程 http://www.runoob.com/design-pattern/adapter-pattern.html 我用了和他不同的例子,但是結構都是一樣的。

再來一個例子,加入說我需要處理圖片,但是圖片的格式不同,針對不同格式需要不同的方法來處理。

定義介面和特殊格式處理介面

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: <p>http://www.runoob.com/design-pattern/adapter-pattern.html</p>
 * @Date: 2022-08-27
 */
public interface PictureOperate {
    public void operate(String pictureType, String fileName);
}
package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: 高階圖片處理
 * @Date: 2022-08-27
 */
public interface AdvancedPictureOperate {
    public void operateAi(String fileName);
    public void operateSvg(String fileName);
}

定義處理特殊圖片的類,分別實現各自需要的方法,不需要的放為空方法

package com.lyd.demo.runoob;

/**
 * @Author: lyd
 * @Description: .Ai圖片的操作
 * @Date: 2022-08-27
 */
public class AiOperate implements AdvancedPictureOperate{

    @Override
    public void operateAi(String fileName) {
        System.out.println("操作 " + fileName + " 的ai圖片");
    }

    @Override
    public void operateSvg(String fileName) {
        // todo
    }
}
package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description: .svg圖片的操作
 * @Date: 2022-08-27
 */
public class SvgOperate implements AdvancedPictureOperate {
    @Override
    public void operateAi(String fileName) {
        // todo
    }
    @Override
    public void operateSvg(String fileName) {
        System.out.println("操作 " + fileName + " 的svg圖片");
    }
}

圖片介面卡

根據不同的型別來宣告不同類以及使用對應方法

package com.lyd.demo.runoob;

/**
 * @Author: lyd
 * @Description: 介面卡
 * @Date: 2022-08-27
 */
public class PictureAdapter implements PictureOperate{
    AdvancedPictureOperate advancedPictureOperate;

    public PictureAdapter(String pictureType) {
        if (pictureType.equalsIgnoreCase("ai")) {
            advancedPictureOperate = new AiOperate();
        } else if (pictureType.equalsIgnoreCase("svg")) {
            advancedPictureOperate = new SvgOperate();
        }
    }

    @Override
    public void operate(String pictureType, String fileName) {
        if (pictureType.equalsIgnoreCase("ai")) {
            advancedPictureOperate.operateAi(fileName);
        } else if (pictureType.equalsIgnoreCase("svg")) {
            advancedPictureOperate.operateSvg(fileName);
        }
    }
}

操作類

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description:
 * @Date: 2022-08-27
 */
public class PhotoOperate implements PictureOperate{
    PictureAdapter pictureAdapter;
    @Override
    public void operate(String pictureType, String fileName) {
        if (pictureType.equalsIgnoreCase("ai") || pictureType.equalsIgnoreCase("svg")) {
            pictureAdapter = new PictureAdapter(pictureType);
            pictureAdapter.operate(pictureType, fileName);
        } else if (pictureType.equalsIgnoreCase("jpg")) { // 非特殊格式
            System.out.println("不用特殊方法處理:" + fileName);
        } else {
            System.out.println("格式錯誤");
        }
    }
}

測試

package com.lyd.demo.runoob;
/**
 * @Author: lyd
 * @Description:
 * @Date: 2022-08-27
 */
public class test {
    public static void main(String[] args) {
        PhotoOperate photoOperate = new PhotoOperate();
        photoOperate.operate("jpg", "a.jpg");
        photoOperate.operate("svg", "b.svg");
        photoOperate.operate("ai", "c.ai");
        photoOperate.operate("vip", "d.vip");
    }
}

執行結果

:+1:創作不易,如有錯誤請指正,感謝觀看!記得一鍵三連哦!:+1:

:heartbeat:德德小建議:

理解設計模式不是一件簡單的事情,需要不斷的學習和動手去練習,才能理解。只有掌握好設計模式,才能夠真正的理解SpringAOP和Mybatis的底層原理。各位讀者可以和我一樣,動手敲一敲程式碼,甚至用不同的例子來做,通過debug一步一步除錯,還有就是多看看別人的例子。能夠有助於理解!謝謝各位觀看指點!:heart: :heart: :heart: