一、介紹
1.1 需求場景
在軟體開發中,經常會遇到需要複用既有的類或者接口,但是這些類或接口卻不符合目前系統的需求。例如,在一個系統中,需要使用一個已有的類A,但是該類的接口與目前系統所要求的接口不一緻,此時需要将類A進行适配,以便能夠在目前系統中使用。這就是擴充卡模式的一個經典需求場景。
1.2 什麼是擴充卡模式?
擴充卡模式是一種結構型設計模式,用于将一個類或者接口的接口轉換成另一個接口,以滿足用戶端的需求。擴充卡模式可以在不修改既有類或接口的情況下,将它們的接口進行适配,進而使它們能夠協同工作。
1.3 設計原則和用途
擴充卡模式遵循的設計原則包括依賴倒置原則、單一職責原則、開閉原則等。它的主要用途包括:
- 将已有類或接口适配成符合目前系統需求的類或接口。
- 可以在不修改既有類或接口的情況下,将它們的接口進行适配。
- 可以實作不同的接口之間的适配。
二、經典面向對象的擴充卡模式
2.1 擴充卡模式的基礎類圖和角色
擴充卡模式的基礎類圖包括目标接口(Target)、擴充卡(Adapter)、适配者(Adaptee)和用戶端(Client)四個角色。其中,目标接口是用戶端所期望的接口,擴充卡是将适配者的接口轉換成目标接口的類,适配者是需要被适配的類,用戶端是使用目标接口進行操作的類。
2.2 擴充卡模式的實作步驟
- 定義目标接口,即用戶端所期望的接口。
- 定義擴充卡類,繼承目标接口并包含一個适配者對象。
- 在擴充卡類中實作目标接口的方法,調用适配者對象的相關方法進行适配。
- 在用戶端中使用擴充卡類進行操作。
2.3 Object擴充卡和Class擴充卡的對比
在經典面向對象的擴充卡模式中,擴充卡類可以采用兩種實作方式:Object擴充卡和Class擴充卡。
- Object擴充卡使用組合的方式,将适配者對象作為擴充卡類的一個成員變量,并在擴充卡類中調用适配者對象的方法進行适配。
- Class擴充卡使用繼承的方式,繼承适配者類,并同時實作目标接口,通過在擴充卡類中調用适配者類的方法進行适配。
- Object擴充卡具有更好的靈活性和可複用性,因為它可以适配任何适配者對象,而Class擴充卡隻能适配一個具體的适配者類。但是,Object擴充卡需要在擴充卡類中手動實作所有目标接口的方法,而Class擴充卡可以直接使用适配者類中已有的方法。
三、接口擴充卡模式
3.1 對需求場景的描述
接口擴充卡模式是一種特殊的擴充卡模式,它用于解決用戶端隻需要使用目标接口中的部分方法而不需要全部方法的情況。在這種情況下,用戶端可以通過接口擴充卡模式,僅實作目标接口中需要使用的方法,而不必實作所有方法。
3.2 為什麼需要接口擴充卡模式?
接口擴充卡模式是一種特殊的擴充卡模式,它用于解決用戶端隻需要使用目标接口中的部分方法而不需要全部方法的情況。在這種情況下,用戶端可以通過接口擴充卡模式,僅實作目标接口中需要使用的方法,而不必實作所有方法。
3.3 接口擴充卡模式的基礎類圖和實作步驟
接口擴充卡模式的基礎類圖包括目标接口(Target)、擴充卡(Adapter)、适配者(Adaptee)和用戶端(Client)四個角色。其中,目标接口是用戶端所期望的接口,擴充卡是将适配者的接口轉換成目标接口的類,适配者是需要被适配的類,用戶端是使用目标接口進行操作的類。 接口擴充卡模式的實作步驟包括:
- 定義目标接口,包含用戶端所需要使用的方法。
public interface Target {
void methodA();
void methodB();
}
- 定義擴充卡類,實作目标接口,并使用抽象類或者預設實作來适配目标接口。
public abstract class AbstractAdapter implements Target {
public void methodA() {
// 預設實作
}
public void methodB() {
// 預設實作
}
// 适配目标接口中未實作的方法
public abstract void methodC();
}
- 定義适配者類,包含所有方法,并實作抽象擴充卡類中的方法。
public class Adaptee {
public void methodA() {
// 實作methodA的邏輯
}
public void methodB() {
// 實作methodB的邏輯
}
public void methodC() {
// 實作methodC的邏輯
}
}
- 定義擴充卡類,繼承抽象擴充卡類并包含一個适配者對象,實作目标接口中需要使用的方法,并調用适配者對象的方法進行适配。
public class Adapter extends AbstractAdapter {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void methodA() {
adaptee.methodA();
}
public void methodB() {
adaptee.methodB();
}
public void methodC() {
// 實作methodC的邏輯
}
}
- 在用戶端中使用擴充卡類進行操作。
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target adapter = new Adapter(adaptee);
adapter.methodA(); // 調用擴充卡中的methodA方法
adapter.methodB(); // 調用擴充卡中的methodB方法
adapter.methodC(); // 調用擴充卡中的methodC方法
}
}
通過上述實作步驟,即可使用接口擴充卡模式将适配者類的接口轉換成目标接口,并在用戶端中使用目标接口進行操作。
四、擴充卡模式的應用
4.1 對現實世界的例子的解釋
擴充卡模式是一種結構型設計模式,它允許現有的類或接口與其他類或接口進行相容。擴充卡模式通過建立一個新的擴充卡類,将一個或多個現有類或接口進行包裝,并使其符合其他類或接口的接口規範。擴充卡模式常常用于軟體系統中不同元件之間的內建,以及在軟體開發過程中對現有代碼進行重構的情況。
例如,假設你正在開發一個新的應用程式,這個應用程式需要連接配接到一個已有的資料庫。這個資料庫使用了一個非常老舊的接口,它的接口規範與現代的資料庫接口完全不同。在這種情況下,你可以使用擴充卡模式來建立一個新的擴充卡類,将現代的資料庫接口轉換為舊有的接口規範,進而讓你的應用程式能夠與這個舊有的資料庫進行內建。
4.2 Web服務API擴充卡的實作
Web服務API擴充卡是擴充卡模式在Web服務開發中的一種常見應用。Web服務是一種通過網絡提供的應用程式接口(API),它可以讓不同的應用程式通過網絡進行通信。Web服務通常使用一些标準協定和格式,如SOAP(Simple Object Access Protocol)、XML(Extensible Markup Language)和WSDL(Web Services Description Language)。
在Web服務開發中,使用擴充卡模式可以将現有的應用程式接口與标準的Web服務API進行适配。例如,如果你的應用程式使用了一些自定義的API接口,但是你希望将這些API接口暴露給其他應用程式通過Web服務進行通路,你可以使用擴充卡模式來建立一個新的擴充卡類,将自定義的API接口轉換為标準的Web服務API接口規範,進而讓其他應用程式能夠通過Web服務通路你的API接口。
五、擴充卡模式的優缺點
5.1 優點
- 提高代碼的複用性。擴充卡模式允許你重複使用現有的類或接口,而不需要修改它們的代碼,進而提高了代碼的複用性。
- 提高系統的靈活性。擴充卡模式可以将不相容的接口轉換為相容的接口,進而提高了系統的靈活性,使得系統更加容易進行擴充和維護。
- 支援多态性。擴充卡模式可以将不同的實作封裝在同一個擴充卡接口中,進而支援多态性。
5.2 缺點
- 增加代碼複雜性。擴充卡模式需要建立一個新的擴充卡類,進而增加了代碼的複雜性和維護成本。
- 降低系統的性能。擴充卡模式需要進行額外的轉換和處理,可能會對系統的性能産生一定的影響。
- 可能會隐藏系統的缺陷。擴充卡模式可能會隐藏系統的一些缺陷,使得這些缺陷在系統中長期存在而不被發現和修複。
六、示例代碼
6.1 經典面向對象的擴充卡模式代碼示例
// 目标接口
interface Target {
void request();
}
// 被适配的類
class Adaptee {
public void specificRequest() {
System.out.println("Adaptee specific request");
}
}
// 擴充卡類
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
// 用戶端代碼
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
6.2 接口擴充卡模式代碼示例
// 目标接口
interface TargetInterface {
void methodA();
void methodB();
void methodC();
}
// 抽象擴充卡類
abstract class Adapter implements TargetInterface {
@Override
public void methodA() {}
@Override
public void methodB() {}
@Override
public void methodC() {}
}
// 具體擴充卡類
class ConcreteAdapter extends Adapter {
private Adaptee adaptee;
public ConcreteAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void methodA() {
adaptee.method1();
}
@Override
public void methodB() {
adaptee.method2();
}
}
// 被适配者接口
interface Adaptee {
void method1();
void method2();
void method3();
}
// 被适配者實作類
class ConcreteAdaptee implements Adaptee {
@Override
public void method1() {}
@Override
public void method2() {}
@Override
public void method3() {}
}
// 用戶端代碼
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new ConcreteAdaptee();
TargetInterface target = new ConcreteAdapter(adaptee);
target.methodA();
target.methodB();
}
}
作者:陳書予
連結:https://juejin.cn/post/7232309550259208249
來源:稀土掘金