適配器模式的出現(xiàn)是為了滿足各種不同的需求,我們在做開發(fā)的時候,經(jīng)常會用到一個中間層來進行適配,這個中間層就起到了適配器模式的作用。
學習的時候,有一個很好的例子就是筆記本對電壓的要求和家庭電壓的矛盾,總是筆記本需要一個變壓器來解決這個問題,變壓器便是一個適配器。
給一個相關(guān)的偽代碼:
//Target
public interface ComputerVolt {
public int computerVolt();
}
//Adaptee
public class HomeVolt {
public int homeVolt() {
return 220;
}
}
//adapter
public class ClassAdapter extends HomeVolt implements ComputerVolt {
@Override
public int computerVolt() {
return 12;
}
}
通過這個方式我們就成功的解決了電源適配的問題,ClassAdapter就是適配器,這就是一個簡單的適配器模式。
適配器模式可分為兩種:
一種是類適配器模式(繼承方式)
一種是對象適配器模式(委托方式)
類適配器模式
一個簡單的需求場景:
一段文字需要翻譯為中文和英文,根據(jù)這個場景我們來一步一步完成繼承方式的適配器模式。
首先我們有一個類專門為顯示中文和英文的功能:
public class Display {
private String word;
public Display(String word) {
this.word = word;
}
//顯示中文
public void displayChinese() {
............chinese..........
}
public void displayEnglish() {
...........English............
}
}
而我們需要的翻譯功能的接口為:
public interface Translation {
void chinese2English();
void english2Chinese();
}
為了實現(xiàn)我們的翻譯需求,此時便需要一個適配器的角色:
public class TranslationImpl extends DisPlay implements Translation {
public TranslationImpl(String word) {
super(word);
}
@Override
public void chinese2English() {
displayEnglish();
}
@Override
public void english2Chinese() {
displayChinese();
}
}
接下來看看測試函數(shù):
public class Main {
public static void main(String[] args) {
Translation trans = new TranslationImpl("test");
trans.english2Chinese();
trans.chinese2English();
}
}
通過測試代碼,我們發(fā)現(xiàn)暴露在外面的只是Translation接口,Display類對于使用者來說是完全處于不存在狀態(tài)的,而且也不知道TranslationImpl是如何實現(xiàn)翻譯功能的,就好比我們在使用筆記本的時候并不知道電源適配器是怎么將家庭電壓轉(zhuǎn)化為筆記本的適用電壓。如果我們需要修改實現(xiàn)方式,我們直接修改其實現(xiàn)方式,完全不影響其他端。
對象適配器模式
對象適配器模式,委托方式,簡單來說就是交給其他實例來完成需要實現(xiàn)的功能。
我們依然采用剛才的例子來解釋對象適配器,不過在這里我把之前的Translation接口改成一個類,由于在Java中是單繼承模式,因此我們TranslationImpl不能同時作為Translation和Display的子類存在,但是根據(jù)對象適配器模式的委托思想,我們應該能夠猜到怎么去實現(xiàn)這個需求了。
首先是Translation類:
public abstract class Translation {
public abstract void chinese2English();
public abstract void english2Chinese();
}
Display類則保持不變、最后是TranslationImpl的實現(xiàn)方式:
public class TranslationImpl extends Translation {
private Display display;
public TranslationImpl(String word) {
display = new Display(word);
}
@Override
public void chinese2English() {
display.displayEnglish();
}
@Override
public void english2Chinese() {
display.displayChinese();
}
}
實現(xiàn)思想就是:
將Display的實例以TranslationImpl的變量的形式保存,且在TranslationImpl構(gòu)造函數(shù)類生成,其展示方法我們通過變量的形式來調(diào)用,這就相當于我們將要執(zhí)行的任務委托給了Display的實例去實現(xiàn)。
什么時候適用
做開發(fā)的時候,并不是都是從零開始,很多時候都是在已有的項目基礎上進行擴展,因此很多東西可能都是已有的,而且是經(jīng)過很多次檢驗的代碼,因此我們更愿意復用這類代碼,而不是重新去編寫。而且該模式是適配現(xiàn)有的類產(chǎn)生新類,因此產(chǎn)生問題后,我們能夠快速定位問題到新產(chǎn)生的類進行分析,而不會出現(xiàn)在現(xiàn)有的類中,能夠節(jié)約很大的開發(fā)成本。