關於適配器模式的定義,我就直接引用Head First了:適配器模式將一個類的接口,轉換成客戶期望的另一個接口。適配器讓原本接口不兼容的類可以合作無間。 適配器模式的意圖是進行接口的轉換,這點很重要,這是區分裝飾者模式的“擴展行爲”和代理模式的“訪問控制”的依據。
適配器模式
其實學設計模式,不能拘泥於格式,不能死記形式,重要的是要理解模式背後的意圖,意圖只有一個,但實現的形式卻可能多種多樣。這也就是爲何那麼多變體依然屬於xx設計模式的原因。假如有硬件廠商提供一種智能音箱,其對外提供了“打開”和“關閉”兩個接口:
這是智能設備接口類。
public interface Ihardware {
void on();
void off();
}
這是具體的智能音箱類:
public class SpeakerBox implements Ihardware {
@Override public void on() {
System.out.println("打開音箱");
}
@Override public void off() {
System.out.println("關閉音箱");
}
}
現廠商對所屬硬件進行了技術升級,發現“關閉”接口並不常用,所以替換成了“休眠”接口,現智能設備接口類2.0見下:
public interface Ihardware2 {
void on();
void sleep();
}
這是新版智能音箱類2.0具體類:
public class SpeakerBox2 implements Ihardware2 {
@Override public void on() {
System.out.println("體驗版-打開音箱");
}
@Override public void sleep() {
System.out.println("體驗版-休眠音箱");
}
}
公司A,一直是該廠商智能音箱的忠實用戶,今天在將智能音箱從1.0升級到2.0後,發現已有的業務無法正常運行了。在痛斥硬件廠商私自更改公開接口外,公司A的工程師只能先進行緊急修復。
爲了兼容老版本和儘可能少的代碼改動,工程師老王提出:我們要將不兼容的接口變成兼容的接口。可怎麼將2.0的接口轉換成客戶期待的1.0接口呢?適配器對象見下:
public SpeakerBox2Adapter implements Ihardware {
private SpeakerBox2 mSb2;
public SpeakerBox2Adapter(SpeakerBox2 sb2) {
this.mSb2 = sb2;
}
@Override public void on() {
mSb2.on();
}
@Override public void off() {
/**
* 當然這裏可以進行一系列的轉換邏輯。
*/
mSb2.sleep();
}
}
通過適配器對象,我們就能對SpeakerBox2 對象像SpeakerBox一樣使用了。測試代碼見下:
public class ClientTest {
public static void main(String[] ags) {
Ihardware hw1 = new SpeakerBox();
Ihardware hw2 = new SpeakerBox2Adapter(new SpeakerBox2());
// 接口調用
hw1.on();
hw1.off();
hw2.on();
hw2.off();
}
}