java設(shè)計模式之適配器模式
感謝《Android源碼設(shè)計模式解析與實戰(zhàn)》 何紅輝 關(guān)愛民 著
適配器模式在我們的開發(fā)中使用率極高,從代碼中隨處可見的Adapter就可以判斷出來,從最早的ListView、GridView、到現(xiàn)在最新的RecyclerView都需要使用Adapter,并且在開發(fā)中我們遇到的優(yōu)化問題、出錯概率較大的地方也基本都出自Adapter。
適配器是將兩個不兼容的火龍融合在一起,將不同的東西通過一種轉(zhuǎn)換使得它們能夠協(xié)作起來,例如,經(jīng)常碰到要在兩個沒有關(guān)系的類型之間進(jìn)行交互,第一個解決方案是修改各自類的接口,但是如果沒有源代碼或者我們不愿意為了一個應(yīng)用而修改各自的接口,這種情況我們往往會使用一個Adapter,這個Adapter會將這兩個接口進(jìn)行兼容,在不修改原有代碼的情況下滿足需求。
假設(shè)已有一個軟件系統(tǒng),你希望它能和一個新的廠商類庫搭配使用,但是這個新廠商所設(shè)計出來的接口,不用于舊廠商的接口:

你不想改變現(xiàn)有的代碼,解決這個問題(也不能改變廠商的代碼),應(yīng)該怎么做?你可以寫一個類(適配器),將新廠商接口轉(zhuǎn)接成你所期望的接口,這個適配器工作起來就如同一個中間人,它將客戶所發(fā)出的請求轉(zhuǎn)換成廠商類能理解的請求。

適配器模式可分為兩種:
對象適配器:充滿著良好的OO設(shè)計原則,使用對象組合,可以應(yīng)用在適配者是接口和它所有的子類,不能夠重寫適配器的方法,因為沒有繼承關(guān)系,但是也能夠“重新實現(xiàn)”適配者中方法,客戶端和適配者完全不相干,只有適配器擁有適配者的引用。
類適配器:使用繼承的方式達(dá)到適配的工作,只能是適配者是接口,不能利用它子類的接口,當(dāng)類適配器建立時,它就靜態(tài)地與適配者關(guān)聯(lián),適配者作為適配器的基類,所以適配器能夠重寫適配器中的方法,客戶端代碼對適配者中聲明的代碼是可見的客戶端代碼對適配者中聲明的代碼是可見的。
定義:
適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
使用場景:
1.系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要,即接口不兼容。
2.想要建立一個可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作。
3.需要一個統(tǒng)一的輸出接口,而輸入端的類型不可預(yù)知。
UML類圖:
首先看下類適配器:
類適配器是通過實現(xiàn)Target接口以及繼承Adaptee類來實現(xiàn)接口轉(zhuǎn)換,例如,目標(biāo)接口需要的是operation2,但是Adaptee對象只有一個operation3,因此就出現(xiàn)了不兼容的情況。此時通過Adapter實現(xiàn)一個operation2函數(shù)將Adaptee的operation3轉(zhuǎn)換成Target需要的operation2,以此實現(xiàn)兼容。
Target : 目標(biāo)角色,也就是所期待得到的接口。注意:由于這里討論的是類適配器模式,因此目標(biāo)不可以是類。
Adaptee : 現(xiàn)在需要適配的接口。
Adapter: 適配器角色,也是本模式的核心,適配器把源接口轉(zhuǎn)換成目標(biāo)接口。這一角色不可以是接口,而必須是具體類。
類適配器模式示例:
以大陸電壓為220v,手機(jī)電壓為5v為例
/**
* 電壓類 Target目標(biāo)
* @author Administrator
*
*/
public interface Voltage {
public int getVoltage();
}public class ChinaVoltage implements Voltage{
@Override
public int getVoltage() {
// 大陸電壓為220
return 220;
}
}<pre name="code" class="java">/**
* 手機(jī)類, Adaptee 被適配者類
* @author Administrator
*
*/
public class PhoneVoltage {
/**
* 手機(jī)電壓為5v
* @return
*/
public int getPhoneVoltage(){
return 5;
}
}
<pre name="code" class="java">/**
* 充電器 Adapter 適配器類
* @author Administrator
*
*/
public class Charger extends PhoneVoltage implements Voltage {
@Override
public int getVoltage() {
return getPhoneVoltage();
}
}
public class Client {
public static void main(String[] args) {
ChinaVoltage vol = new ChinaVoltage();
System.out.println("大陸電壓為 : " + vol.getVoltage());
//為手機(jī)接入充電器時的電壓
Chargerr character = new Chargerr();
System.out.println("通過充電器轉(zhuǎn)換后的電壓 : " + character.getVoltage());
}
}
運行結(jié)果:
大陸電壓為 : 220
通過充電器轉(zhuǎn)換后的電壓 : 5
再看一下對象適配器類圖:

下面以對象適配器修改Chargerr類
<pre name="code" class="java">/**
* 充電器 Adapter 適配器類
* @author Administrator
*
*/
public class Chargerr implements Voltage{
private PhoneVoltage phoneV;
public Chargerr(PhoneVoltage phoneV) {
this.phoneV = phoneV;
}
@Override
public int getVoltage() {
return phoneV.getPhoneVoltage();
}
}
對象適配器實現(xiàn)方式直接將要被適配的對象傳遞到Adapter中,使用組合的形式實現(xiàn)接口兼容的效果,這比類適配器方式更為靈活,它的另一個好處是被適配對象中的方法不會暴露出來,而類適配器由于繼承了被適配對象,因此,被適配對象類的函數(shù)在Adapter類中也都含有,這使得Adapter類出現(xiàn)一些奇怪的接口,用戶使用成本較高。因此,對象適配器模式更加靈活、實用。
public class Client {
public static void main(String[] args) {
// ChinaVoltage vol = new ChinaVoltage();
// System.out.println("大陸電壓為 : " + vol.getVoltage());
// //為手機(jī)接入充電器時的電壓
// Chargerr character = new Chargerr();
// System.out.println("通過充電器轉(zhuǎn)換后的電壓 : " + character.getVoltage());
//被適配者
PhoneVoltage phoneV = new PhoneVoltage();
Chargerr chargerr = new Chargerr(phoneV);
System.out.println("通過充電器轉(zhuǎn)換后的電壓:" + chargerr.getVoltage());
}
//運行結(jié)果:
// 通過充電器轉(zhuǎn)換后的電壓:5
}
總結(jié):
Adapter模式的經(jīng)典實現(xiàn)在于將原本不兼容的接口融合在一起,使之能夠很好地進(jìn)行合作。但是,在實際開發(fā)中,Adapter模式也有一些靈活的實現(xiàn)。例如ListView中的隔離變化,使得整個UI架構(gòu)變得更靈活,能夠擁抱變化。Adapter模式在開發(fā)呂運用非常廣泛。
優(yōu)點:
更好的復(fù)用性:系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復(fù)用。
更好的擴(kuò)展性:在實現(xiàn)適配器功能的時候,可以調(diào)用自己開發(fā)的功能,從而自然地擴(kuò)展系統(tǒng)的功能。
缺點:
過多的使用適配器,會讓系統(tǒng)非常零亂,不易速體把握。例如,明明看到調(diào)用的昌A接口,其實內(nèi)部被適配成了B接口的實現(xiàn),一個系統(tǒng)如果太多出現(xiàn)這種情況,無異于一場災(zāi)難。因此,如果不是有必要,可以不使用適配器,而是直接對系統(tǒng)進(jìn)行重構(gòu)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合SpringBoot-Admin實現(xiàn)監(jiān)控應(yīng)用功能
本文主要介紹如何整合Spring Boot Admin,以此監(jiān)控Springboot應(yīng)用,文中有相關(guān)的示例代碼供大家參考,需要的朋友可以參考下2023-05-05
Java transient關(guān)鍵字與序列化操作實例詳解
這篇文章主要介紹了Java transient關(guān)鍵字與序列化操作,結(jié)合實例形式詳細(xì)分析了java序列化操作相關(guān)實現(xiàn)方法與操作注意事項,需要的朋友可以參考下2019-09-09
SpringBoot中動態(tài)更新@Value配置方式
這篇文章主要介紹了SpringBoot中動態(tài)更新@Value配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
部署springboot打包不打包配置文件,配置文件為外部配置文件使用詳解
在Spring Boot項目中,將配置文件排除在jar包之外,通過外部配置文件來管理不同環(huán)境的配置,可以實現(xiàn)靈活的配置管理,在pom.xml文件中添加相關(guān)配置,打包時忽略指定文件,運行時在jar包同級目錄下創(chuàng)建config文件夾,將配置文件放入其中即可2025-02-02
spring學(xué)習(xí)之@SessionAttributes實例解析
這篇文章主要介紹了spring學(xué)習(xí)之@SessionAttributes實例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02
Java實現(xiàn)讀取Excel文件功能(EasyExcel初使用)
EasyExcel是一款基于Java語言的開源Excel解析工具,可以幫助我們快速、高效地讀取和寫入Excel文件,這篇文章主要給大家介紹了關(guān)于Java實現(xiàn)讀取Excel文件功能的相關(guān)資料,使用的是EasyExcel,需要的朋友可以參考下2024-07-07
如何解決SpringBoot2.x版本對Velocity模板不支持的方案
這篇文章主要介紹了如何解決SpringBoot2.x版本對Velocity模板不支持的方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12

