DesignPattern - 適配器模式【結構型】

歡迎關注微信公衆號:FSA全棧行動 👋java

1、適配器模式介紹

適配器模式(Adapter Pattern)屬於結構型模式,做爲兩個不兼容的接口之間的橋樑。數據庫

  • 常見的幾類適配器
    • 接口的適配器模式【空實現】:不想實現一個接口中全部的方法時,能夠建立一個 Adapter,實現全部方法,在寫別的類的時候,繼承這個 Adapter 類便可。
    • 類的適配器模式【繼承(舊) + 實現(新)】:想將一個類轉換成知足另外一個新接口的類時,可使用類的適配器模式,建立一個新類,繼承原有的類,實現新的接口便可。
    • 對象的適配器模式【組合】:想將一個對象轉換成知足另外一個新接口的對象時,能夠建立一個適配器類,持有原類的一個實例,在適配器類的方法中,調用實例的方法就行。
  • 應用場景
    • 電腦須要讀取內存卡的數據,讀卡器就是適配器
    • 平常使用的轉換頭,如電源轉換頭,電壓轉換頭
    • 系統須要使用如今的類,而這些類的接口不符合系統的須要(如:JDK 中 InputStreamReader 就是適配器)
    • JDBC 使用的就是適配器模式,jDBC 給出一個客戶端通用的抽象接口,每個具體數據庫廠商,如 SQL Server、Oracle、MySQL 等,會開發對應的 JDBC 驅動,這個 JDBC 驅動就是一個介於 JDBC 接口和數據庫引擎接口之間的適配器軟件。
  • 優勢
    • 可讓任何兩個沒有關聯的類一塊兒運行,使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做
    • 增長靈活度,提升複用性,適配器類能夠在多個系統使用,符合開閉原則
  • 缺點
    • 總體類的調用鏈路增長,原本 A 能夠直接調用 C,使用適配器後,是 A 調用 B,B 再調用 C

補充:適配器模式用於設計完成以後,發現類、接口之間沒法一塊兒工做,須要進行填坑。編程

2、適配器模式代碼實現

一、接口適配器模式

有些接口中有多個抽象方法,當咱們寫該接口的實現類時,必須實現該接口的全部方法,有時會以爲比較冗餘,由於並非全部的方法都是咱們須要的,只須要實現部分接口就能夠了。微信

建立支付網關接口:markdown

/** * 支付網關接口 * * @author GitLqr */
public interface IPayGateway {

	/** * 下單 */
	void order();

	/** * 退款 */
	void refund();

	/** * 查詢 */
	void query();

	/** * 發紅包 */
	void sendRedPack();

    ...
}
複製代碼

建立接口適配器類:ide

/** * 接口適配器:提供全部接口的默認實現 * * @author GitLqr */
public class PayGatewayAdapter implements IPayGateway {

	@Override
	public void order() {
	}

	@Override
	public void refund() {
	}

	@Override
	public void query() {
	}

	@Override
	public void sendRedPack() {
	}

}
複製代碼

建立具體業務類:oop

/** * 視頻VIP訂購:只有訂購和退款功能 * * @author GitLqr */
public class VideoVipOrder extends PayGatewayAdapter {
	@Override
	public void order() {
		System.out.println("視頻VIP 訂購成功");
	}

	@Override
	public void refund() {
		System.out.println("視頻VIP 退款成功");
	}
}
複製代碼

說明:相比於實現 IPayGateway 接口,繼承 PayGatewayAdapter 適配器類,可讓 VideoVipOrder 中代碼簡潔很多。this

二、類的適配器模式

想將一個類轉換成知足另外一個新接口的類時,可使用類的適配器模式,建立一個新類,繼承原有的類,實現新的接口便可。spa

建立 舊類:設計

說明:【舊類】對應的是工程中本來就存在的類,可以穩定運行,可是不支持一些新功能。實際開發中,這些舊類實現可能至關複雜(多是屎山),不能輕易改動!!

/** * 舊類:端口,只能支持usb * * @author GitLqr */
public class Port {
	public void usb(Object usbDevice) {
		System.out.println("插入 usb 設備");
	}
}
複製代碼

建立 新功能接口:

說明:該【新功能接口】通常擁有 舊類 中的方法,方便後續面向接口編程

/** * 新接口:須要支持舊端口類型(usb)的同時,支持更多的新端口類型(如 typec、usb4) * * @author GitLqr */
public interface INewPort {

	void usb(Object usbDevice);

	void typec(Object typecDevice);

	void usb4(Object usb4Device);
}
複製代碼

建立 新類:

說明:【新類】須要繼承【舊類】,同時實現【新功能接口】

/** * 新類:端口適配器【擴展塢】 * * @author GitLqr */
public class PortAdapter extends Port implements INewPort {

	@Override
	public void typec(Object typecDevice) {
		System.out.println("插入 type-c 設備");
	}

	@Override
	public void usb4(Object usb4Device) {
		System.out.println("插入 雷電4 設備");
	}

}
複製代碼

使用:

public static void main(String[] args) {
	...
    INewPort newPort = new PortAdapter();
    newPort.usb(usbDevice); // 老功能 也能正常使用
    newPort.typec(typecDevice);
    newPort.usb4(usb4Device);
}
複製代碼

三、對象的適配器模式

想將一個對象轉換成知足另外一個新接口的對象時,能夠建立一個適配器類,持有原類的一個實例,在適配器類的方法中,調用實例的方法就行。

對象的適配器更像是一種包裝(或加強),實際功能還須要藉助原對象來執行處理,就好比充電器插頭問題,插頭轉換器只是改變了充電器插頭的類型,實際上給手機充電的,仍是充電器自己。

建立 充電器類:

/** * 充電器 * * @author GitLqr */
public class Charger {

	void charge() {
		System.out.println("充電中...");
	}
}
複製代碼

建立 新接口(支持多種插頭轉換):

/** * 接口:各式插頭 * * @author GitLqr */
public interface IPlugConverter {

	/** * 雙腳插頭充電 */
	void chargeOnTwoPin();

	/** * 三腳插頭充電 */
	void chargeOnThreePin();

	/** * 三腳插頭充電(港版插座) */
	void chargeOnThreePinHK();

}
複製代碼

建立 知足 新接口 的 適配器類:

/** * 充電器插頭適配器 * * @author GitLqr */
public class ChargerPlugAdapter implements IPlugConverter {

	private Charger charger;

	public ChargerPlugAdapter(Charger charger) {
		super();
		this.charger = charger;
	}

	@Override
	public void chargeOnTwoPin() {
		charger.charge();
	}

	@Override
	public void chargeOnThreePin() {
		System.out.println("使用三腳插頭");
		charger.charge();
	}

	@Override
	public void chargeOnThreePinHK() {
		System.out.println("使用港版三腳插頭");
		charger.charge();
	}

}
複製代碼

若是文章對您有所幫助, 請不吝點擊關注一下個人微信公衆號:FSA全棧行動, 這將是對我最大的激勵. 公衆號不只有Android技術, 還有iOS, Python等文章, 可能有你想要了解的技能知識點哦~

相關文章
相關標籤/搜索