一、介紹
適配器模式主要是為了解決系統(tǒng)中兩個接口實(shí)現(xiàn)某個或某類功能但又不兼容的問題,比如國內(nèi)居民用電電壓是220V,手機(jī)充電輸入電壓是5V,在給手機(jī)充電時需要將220V電壓轉(zhuǎn)換為5V,這個轉(zhuǎn)換裝置就可以理解為適配器,軟件編程中有時也需要用到這種思想,解決這類問題就需要用到適配器模式。
適配器模式細(xì)分為類適配器模式、對象適配器模式和接口適配器模式三種。
二、示例
1、類適配器模式
類適配器模式是指適配器類通過繼承源對象類,實(shí)現(xiàn)目標(biāo)接口的方式,在適配器類中實(shí)現(xiàn)目標(biāo)接口定義的方法,在實(shí)現(xiàn)方法中調(diào)用源對象類方法并作相關(guān)轉(zhuǎn)換,從而輸出想要的結(jié)果。
1.1、UML類圖

在這個例子中,Voltage5VAdapter適配器類繼承源對象類Voltage220V,實(shí)現(xiàn)目標(biāo)對象接口IVoltage5V,實(shí)現(xiàn)IVoltage5V接口中定義的out方法,通過調(diào)用Voltage220V類中output方法獲得源對象輸出的電壓,轉(zhuǎn)換成需要的電壓輸出,手機(jī)類Phone調(diào)用charging方法開始充電,客戶端類Client實(shí)現(xiàn)整個系統(tǒng)的運(yùn)行。
1.2、代碼
public class Voltage5VAdapter extends Voltage220V implements Voltage5V{
@Override
public int out() {
return output()/44;
}
}
public class Phone {
public void charging(Voltage5VAdapter adapter){
if (adapter.out() > 5){
System.out.println("電壓不對,無法充電");
}else {
System.out.println("充電中。。。");
}
}
}
1.3、小結(jié)
由于Java的單繼承機(jī)制,在類適配器模式中,由于繼承了源對象,所以目標(biāo)對象只能是接口形式,這有一定的局限。同時繼承也會使得父類中一些方法暴露給了子類,增加了耦合度。
2、對象適配器模式
為解決類適配模式中目標(biāo)對象只能是接口的限制,對象適配器模式中,適配器類不再繼承源對象,源對象以全局變量形式聚合到適配器類中,這樣目標(biāo)對象可以是接口也可以是抽象類,同時繼承的減少,耦合度也降低。
2.1、UML類圖

在這種模式下,源對象Voltage220V以全局變量的形式聚合到適配器類Voltage5VAdapter中,在構(gòu)造方法中傳入源對象實(shí)例,目標(biāo)對象方法實(shí)現(xiàn)中通過源對象實(shí)例去調(diào)用相關(guān)方法做轉(zhuǎn)換,最后輸出結(jié)果。
2.2、代碼
public class Voltage5VAdapter extends Voltage5V{
private final Voltage220V voltage220V;
public Voltage5VAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int out() {
return voltage220V.output()/44;
}
}
public class Phone2 {
public void charging(Voltage5VAdapter adapter){
if (adapter.out() > 5){
System.out.println("電壓不對不能充電");
}else {
System.out.println("充電中...");
}
}
}
2.3、小結(jié)
源對象以全局變量的形式聚合到適配器類中,目標(biāo)對象可以是接口形式,也可以是抽象類形式,系統(tǒng)更加靈活。
3、接口適配器模式
接口適配器模式主要是為了解決實(shí)現(xiàn)類不需要實(shí)現(xiàn)接口中定義的全部方法這一問題,比如一個接口中定義了很多個方法,但實(shí)現(xiàn)者只用到其中一個,如果直接實(shí)現(xiàn)接口,那么全部方法都會以空實(shí)現(xiàn)的形式存在類中,實(shí)現(xiàn)類會顯得臃腫,如果是匿名內(nèi)部類去實(shí)現(xiàn),那代碼可讀性更差,為解決這一問題,我們可以用一個抽象類去實(shí)現(xiàn)接口,外部調(diào)用傳入抽象類,這樣就可以需要哪個方法就只用實(shí)現(xiàn)哪個方法即可。
public interface IInterface {
void f1();
void f2();
void f3();
}
public abstract class AbsInterfaceAdapter implements IInterface{
@Override
public void f1() {
}
@Override
public void f2() {
}
@Override
public void f3() {
}
}
public class Main {
public static void main(String[] args){
AbsInterfaceAdapter adapter = new AbsInterfaceAdapter() {
@Override
public void f1() {
super.f1();
System.out.println("外部只實(shí)現(xiàn)f1方法");
}
};
adapter.f1();
}
}
三、總結(jié)
我是搞Android,要說Android中適配器,最常見和常用那莫過于RecyclerView的Adapter了,在這套系統(tǒng)中,Adapter適配器主要是作為data和view的橋梁,解決數(shù)據(jù)顯示在控件上的適配兼容問題,data作為源對象,以全局變量的形式聚合在adapter類中,同時adapter類實(shí)現(xiàn)了ViewHolder這個目標(biāo)接口,通常我們需要自建一個類去實(shí)現(xiàn)ViewHolder接口,實(shí)現(xiàn)getItem(),在這個方法中通過findViewById找到各個控件返回,然后通過ViewHolder對象取到哥哥控件對象進(jìn)行data賦值,這樣數(shù)據(jù)就顯示到了控件上,這里用到了對象適配器模式,由于類適配器模式的限制,平時開發(fā)中最常用的還是對象適配器模式。
學(xué)習(xí)了設(shè)計(jì)模式再結(jié)合到項(xiàng)目中,不得不感嘆設(shè)計(jì)模式之類。