設計模式分類
-
結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
-
行爲型模式:模版方法模式、命令模式、訪問者模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter 模式)、狀態模式、策略模式、職責鏈模式(責任鏈模式)。
適配器模式
基本介紹
-
適配器模式(Adapter Pattern)將某個類的接口轉換成客戶端期望的另一個接口表示,主的目的是兼容性,讓原本因接口不匹配不能一起工作的兩個類可以協同工作。其別名爲包裝器(Wrapper)
-
適配器模式屬於結構型模式
-
主要分爲三類:類適配器模式、對象適配器模式、接口適配器模式
類適配器模式
工作原理
-
適配器模式:將一個類的接口轉換成另一種接口。讓原本接口不兼容的類可以兼容
-
從用戶的角度看不到被適配者,是解耦的
-
用戶調用適配器轉化出來的目標接口方法,適配器再調用被適配者的相關接口方法
-
用戶收到反饋結果,感覺只是和目標接口交互
需求
在現實生活中,我們日常使用的電網都是220V的,但是我們的手機充電電壓卻比較低,期間需要一個適配過渡的過程。
UML類圖
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charge(new VoltageAdapter());
}
}
//電壓220V輸出類
class Volatage220V {
public int output220V() {
int src = 220;
System.out.println("電壓:"+ src +"V");
return src;
}
}
// 電壓5V輸出接口
interface Voltage5V {
int output5V();
}
// 電壓適配器類
class VoltageAdapter extends Volatage220V implements Voltage5V {
@Override
public int output5V() {
int srcV = output220V();
int dstV = srcV / 44;
System.out.println("類適配器:將220V電壓轉換爲5V");
return dstV;
}
}
// 手機
class Phone {
public void charge(Voltage5V voltage5V) {
int output5v = voltage5V.output5V();
if(output5v == 5) {
System.out.println("電壓5V,開始充電");
}else {
System.out.println("電壓不是5V,不充電");
}
}
}
結果
注意事項和細節
-
Java是單繼承機制,所以類適配器需要繼承src類這一點算是一個缺點, 因爲這要求dst必須是接口,有一定侷限性;
-
src類的方法在Adapter中都會暴露出來,也增加了使用的成本。
-
由於其繼承了src類,所以它可以根據需求重寫src類的方法,使得Adapter的靈活性增強了。
對象適配器
工作原理
-
基本思路和類的適配器模式相同,只是將Adapter類作修改,不是繼承src類,而是持有src類的實例,以解決兼容性的問題。 即:持有 src類,實現 dst 類接口,完成src->dst的適配
-
根據“合成複用原則”,在系統中儘量使用關聯關係來替代繼承關係。
-
對象適配器模式是適配器模式常用的一種
需求和類適配器一樣,我們來用對象適配器模擬一下剛剛的流程
UML類圖
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charge(new VoltageAdapter(new Volatage220V()));
}
}
//電壓220V輸出類
class Volatage220V {
public int output220V() {
int src = 220;
System.out.println("電壓:"+ src +"V");
return src;
}
}
// 電壓5V輸出接口
interface Voltage5V {
int output5V();
}
// 電壓適配器類
class VoltageAdapter implements Voltage5V {
Volatage220V volatage220V;
public VoltageAdapter(Volatage220V volatage220v) {
volatage220V = volatage220v;
}
@Override
public int output5V() {
if(volatage220V != null) {
int srcV = volatage220V.output220V();
int dstV = srcV / 44;
System.out.println("對象適配器:將220V電壓轉換爲5V");
return dstV;
}
return 0;
}
}
// 手機
class Phone {
public void charge(Voltage5V voltage5V) {
int output5v = voltage5V.output5V();
if(output5v == 5) {
System.out.println("電壓5V,開始充電");
}else {
System.out.println("電壓不是5V,不充電");
}
}
}
結果
注意事項和細節
-
對象適配器和類適配器其實算是同一種思想,只不過實現方式不同。 根據合成複用原則,使用組合替代繼承, 所以它解決了類適配器必須繼承src的侷限性問題,也不再要求dst必須是接口。
-
使用成本更低,更靈活。
接口適配器模式
工作原理
-
一些書籍稱爲:適配器模式(Default Adapter Pattern)或缺省適配器模式。
-
當不需要全部實現接口提供的方法時,可先設計一個抽象類實現接口,併爲該接口中每個方法提供一個默認實現(空方法),那麼該抽象類的子類可有選擇地覆蓋父類的某些方法來實現需求
UML類圖
public class User {
public static void main(String[] args) {
//選擇性實現對應方法即可
new AbsAdapter() {
@Override
public void operation1() {
// TODO Auto-generated method stub
}
@Override
public void operation3() {
// TODO Auto-generated method stub
super.operation3();
}
};
}
}
//
interface Interface {
void operation1();
void operation2();
void operation3();
void operation4();
}
// 接口適配,實現所有接口,方法置空
abstract class AbsAdapter implements Interface{
public void operation1() {}
public void operation2() {}
public void operation3() {}
public void operation4() {}
}
適用場景
適用於一個接口不想使用其所有的方法的情況
總結
-
三種命名方式,是根據 src是以怎樣的形式給到Adapter(在Adapter裏的形式)來 命名的。
-
類適配器:以類給到,在Adapter裏,就是將src當做類,繼承 對象適配器:以對象給到,在Adapter裏,將src作爲一個對象,持有 接口適配器:以接口給到,在Adapter裏,將src作爲一個接口,實現
-
Adapter模式最大的作用還是將原本不兼容的接口融合在一起工作。
-
實際開發中,實現起來不拘泥於我們講解的三種經典形式