1.基本概念
- 將一個接口轉化爲客戶希望的另一個接口,使接口不兼容的那些類可以一起工作,在適配器模式中,我們通過增加一個新的適配器解決接口不兼容的問題,使原本沒有任何關係的類可以協同工作。
2.結構
適配器可以分爲兩種
-
對象適配器 從用戶的角度看不到被適配者,用戶調用適配器轉換出來的接口方法。適配器再調用相關的接口方法,對於用戶來說,用戶感覺只是在和目標接口交互。適配器和適配者是關聯關係
-
類適配器 適配器實現目標接口並且繼承被適配者,適配器和適配者是繼承關係。
3.角色
-
Target(目標抽象類):目標抽象類定義客戶所需接口,可以是一個接口或者抽象類,也可以是具體類
-
Adapter(適配器類):適配器可以調用另外一個接口,作爲一個轉換器,對被適配的角色和目標角色進行適配,在對象適配器中,
-
Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口需要適配,適配者類一般是一個具體類,包含了客戶希望使用的業務方法,在某些情況下可能沒有適配者類的源代碼。
4.案例
將大衆僞裝奔馳
- 對象適配器:
先定義一個奔馳接口,這是目標接口。
public interface BenCar {
void brand();//品牌名稱方法
}
定義大衆接口和大衆的實現類,大衆接口是被適配者。
public interface VolkCar {
void brand();//方法
}
public class VolkCarImpl implements VolkCar {
@Override
public void brand() {
System.out.println("這是奔馳");
}
}
構建適配器,通過有參構造初始化被適配者對象,在實現目標接口裏面調用被適配者的方法,實現僞裝,繼承的是目標接口。實現的是被適配者的方法
//實現奔馳接口,但具體的方法調用的確實大衆接口的。
public class CarAdapter implements BenCar {
private VolkCar volkCar;
public CarAdapter(VolkCar volkCar) {
this.volkCar = volkCar;
}
@Override
public void brand() {
volkCar.brand();
}
}
測試
public class CarTest {
public static void main(String[]args){
VolkCarImpl volkCar = new VolkCarImpl();
BenCar benCar= new CarAdapter(volkCar);
benCar.brand();
}
}
- 類適配器:
類適配器,是通過繼承完成適配過程的,具體和對象適配器很像。我們只用更改下適配器的代碼就可以了。
public class CarAdapter extends VolkCarImpl implements BenCar {
@Override
public void brand() {
super.brand();
}
}
這裏適配器實現了目標接口,但在實現目標接口的方法裏面調的是父類的方法,實現適配。
總而言之,適配器模式就是把不相關的接口聯繫起來,作爲兩個接口的橋樑。
5缺省適配器
缺省適配器主要解決的是我們能夠選擇的適配目標接口中的某個方法。並不想適配所有的方法又稱爲單接口適配器模式。
具體如下。
對於上面的奔馳目標接口,他可能還有一個發動機的方法,但是我們並不像對這個方法進行適配,但我們的適配器又實現這個目標接口,不能不實現這個發動機的方法。
public interface BenCar {
void brand();
void engine();//發動機
}
現在怎麼辦呢,可以創建一個抽象類,對目標接口的方法全部默認實現,如下
public abstract class CarAdapterAbstract implements BenCar {
@Override
public void brand() {
}
@Override
public void engine() {
}
}
更改我們的適配器,繼承抽象類
public class CarAdapter extends CarAdapterAbstract {
private VolkCar volkCar;
public CarAdapter(VolkCar volkCar) {
this.volkCar = volkCar;
}
@Override
public void brand() {
volkCar.brand();
}
}
這樣我們的適配器就可以選擇方法適配了
java源碼好多都用到適配器。比如 Reader、InputStream之間的適配,字符流、字節流之間的適配。大家沒事可以研究研究。