1.問題描述
客戶要求開發日誌管理功能。第一版日誌管理操作實現了讀寫文件,但客戶又想對日誌進行增刪改查功能,因此,根據客戶要求開發第二版。但實現第二版日誌操作的接口後,還想增加數據庫存儲的功能。
問題在於,現在的業務都是使用第二版的接口,對於新加入的保存日誌到數據庫中;但是對於已有的實現方式,它的操作接口和第二版不一樣,因而導致現在客戶端無法以同樣的方式來直接使用第一版的實現,如圖所示:
圖1 問題描述
2.模式引入
將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
3.應用適配器模式來解決問題的思路
上述問題的根源在於接口的不兼容,功能是基本實現了,只要想辦法讓兩邊的接口匹配起來,就可以複用第一版的功能了。
按照適配器模式的實現方式,可以定義一個類來實現第二版的接口,然後在內部實現的時候,轉調第一版已經實現了的功能,通過對象組合的方式,既複用了第一版已有的功能,同時又在接口上滿足了第二版調用的要求。
4.適配器模式實例
圖2 適配器模式實例類圖
- Client:客戶端,調用自己需要的接口Target;
- Target:定義客戶端需要的跟特定功能相關的接口;
- Adaptee:已經存在的接口,通過能滿足客戶端的功能要求,但是接口與客戶端要求的特定功能接口不一致,需要被適配;
- Adapter:適配器,把Adaptee適配成爲Client需要的Target.
圖3 適配器模式實例時序圖
5.適配器模式實例代碼
/**
*
*
* description: 已經存在的接口,這個接口需要適配<br/>
*
* author: fanruifa <br/>
*
* date: 2013-5-21 <br/>
*
*/
public class Adaptee {
public void specificRequest() {
System.out.println("Adaptee實現的請求");
}
}
/**
*
*
* description: 定義客戶端使用的接口,與特定功能相關<br/>
*
* author: fanruifa <br/>
*
* date: 2013-5-21 <br/>
*
*/
public interface Target {
void request();
}
/**
*
*
* description: 適配器<br/>
*
* author: fanruifa <br/>
*
* date: 2013-5-21 <br/>
*
*/
public class Adapter implements Target {
private Adaptee adaptee; // 需要適配的對象
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 轉調實現方法,進行適配
adaptee.specificRequest();
}
}
/**
*
*
* description: 使用適配器客戶端<br/>
*
* author: fanruifa <br/>
*
* date: 2013-5-21 <br/>
*
*/
public class AdapterClient {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
6.適配器模式本質
轉換匹配,複用功能。
7.何時選用適配器模式
- 如果你想使用一個已經存在的類,但是它的接口不符合你的需求,這種情況可以使用適配器模式,來把已有的實現轉換成你需要的接口;
- 如果你想創建一個可以複用的類,這個類可能和一些不兼容的類一起工作,這種情況可以使用適配器模式,到時候需要什麼就適配什麼;
- 如果你想使用一些已經存在的子類,但是不可能對每一個子類都進行適配,這種情況可以先用對象適配器,直接適配這些子類的父類就可以了。