適配器模式

發布日期:2019-10-10

2018年10月17日08:50:11

適配器模式(adapter pattern)

定義

我喜歡的樣子你都有

你喜歡的樣子我有沒有

沒有的話,我送你個適配器,好嗎

將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由于接口不兼容而不能在一起工作的那些類可以一起工作?!对O計模式:可復用面向對象軟件的基礎》

適配器模式是一種對象結構型模式。

使用場景

客戶端需要一個target(目標)接口,但是不能直接重用已經存在的adaptee(適配者)類,因為它的接口和target接口不一致,所以需要adapter(適配器)將adaptee轉換為target接口。前提是target接口和已存在的適配者adaptee類所做的事情是相同或相似,只是接口不同且都不易修改。如果在設計之初,最好不要考慮這種設計模式。凡事都有例外,就是設計新系統的時候考慮使用第三方組件,因為我們就沒必要為了迎合它修改自己的設計風格,可以嘗試使用適配器模式。

角色

目標角色(target):這是客戶鎖期待的接口。目標可以是具體的或抽象的類,也可以是接口

適配者角色(adaptee):已有接口,但是和客戶器期待的接口不兼容。

適配器角色(adapter):將已有接口轉換成目標接口。

分類

適配器模式有分三類:

1、類適配器模式(class adapter pattern)

2、對象適配器模式(object adapter pattern)

3、缺省適配器模式(default adapter pattern),也叫默認適配器模式、接口適配器模式

類適配器模式(class adapter pattern)

類適配器模式在編譯時實現target(目標)接口。這種適配器模式使用了多個實現了期待的接口或者已經存在的接口的多態接口。比較典型的就是:target接口被創建為一個純粹的接口,如Java不支持多繼承的語言。

圖示

類適配器模式(adapter pattern)結構圖:

如上圖,因為java沒有類多繼承,所以只能實現Target接口,而且Target只能是接口。Adapter實現了Target接口,繼承了Adaptee類,Target.operation()實現為Adaptee.specificOperation()。

客戶端調用類適配器:

這個圖是Adapter適配器多繼承的情況,引用維基百科,可以看到客戶端調用適配器Adapter的methodA時候,實際上調用的是Adapter繼承過來的method1到methodN。

代碼示例

一張圖說明需求:

嗯,就是電源適配器了。上面有這樣兩行:

輸入:100-240V ~ 0.5A 50-60HZ

輸出:5.2V ==== 2.4A

我們的需求就是將電源輸入220V(適配者)轉換為5V輸出(目標)。

目標角色(PowerTarget.java):

public interface PowerTarget { public int output5V();}

電源目標。

適配者角色(PowerAdaptee.java):

public class PowerAdaptee { private int output = 220; public int output220V() { System.out.println("電源輸出電壓:" + output); return output; }}

電源適配者。

適配器角色(PowerAdapter.java):

public class PowerAdapter extends PowerAdaptee implements PowerTarget{ @Override public int output5V() { int output = output220V(); System.out.println("電源適配器開始工作,此時輸出電壓是:" + output); output = output/44; System.out.println("電源適配器工作完成,此時輸出電壓是:" + output); return output; } }

電源適配器類實現了電源目標,繼承了適配者。其實如果沒有我打印的那些提示或者說日志,output5V方法可以直接寫成:

public int output5V() { return output220V()/44; }

這樣就適配了。

類適配器模式測試類(ClassAdapterPatternTest.java):

public class ClassAdapterPatternTest { public static void main(String[] args) { PowerTarget target = new PowerAdapter(); target.output5V(); }}

測試結果:

對象適配器模式(object adapter pattern)

對象適配器模式在運行時實現target(目標)接口。在這種適配器模式中,適配器包裝了一個類實例。在這種情況下,適配器調用包裝對象實例的方法。

圖示

對象適配器模式(object adapter pattern)結構圖:

如上圖,與類適配器模式不同的是,Adapter只實現了Target的接口,沒有繼承Adaptee,而是使用聚合的方式引用adaptee。

客戶端調用對象適配器:

客戶端調用對象適配器方法methodA的時候,實際上調用的是創建對象傳進來的適配者實例的方法methodB。

代碼示例

代碼示例和類適配器模式只有Adapter類有不同,其他完成一樣,連測試結果都是一樣。下面只貼上Adapter類。

適配器角色(Adapter.java):

public class PowerAdapter implements PowerTarget{ private PowerAdaptee powerAdaptee; public PowerAdapter(PowerAdaptee powerAdaptee) { super(); this.powerAdaptee = powerAdaptee; } @Override public int output5V() { int output = powerAdaptee.output220V(); System.out.println("電源適配器開始工作,此時輸出電壓是:" + output); output = output/44; System.out.println("電源適配器工作完成,此時輸出電壓是:" + output); return output; } }

實現了PowerTarget(目標角色),在創建對象時引入PowerAdaptee(適配者角色)。

類適配器模式和對象適配器模式的對比

優點

類適配器模式(class adapter pattern):

由于適配器adapter類是適配者adaptee類的子類,因此可以在適配器類中置換一些適配者的方法,即Override(重寫),使得適配器的靈活性更強。

對象適配器模式(object adapter pattern):

一個對象適配器可以把多個不同的適配者adaptee適配到一個目標,也就是說,同一個適配器可以將適配者類和它的子類都適配到目標接口。

缺點

類適配器模式:

java8之前:接口沒有default方法,就是沒有實現了具體邏輯的方法,而且不支持類多繼承,所以適配者類只能有一個。

java8之后:接口有了default方法,接口中的方法有了實現,因為接口是多繼承的,所以適配者可以是多個帶有default方法的接口,但是接口是不可以實例化的,實際上沒有什么意義。有個解決方法就是,接口里都是default方法,實現接口的類什么也沒做,就是提供一個可以實例化的類。這樣的化,類適配器模式中適配者adapter類就可以適配多個適配者adaptee類了。這個解決方法只是我理論上論證一下,實際上可行與否,請自行判斷驗證。

對象適配器模式:

類適配器模式的優點就是對象適配器模式的缺點,不能置換適配者類的方法。如果想修改適配者類的一個或多個方法,就只好先創建一個繼承與適配者類的子類,把適配者類的方法置換掉,然后把適配者的子類當做真正的適配者進行適配,實現過程較為復雜。

缺省適配器模式(default adapter pattern)

當不需要全部實現接口提供的方法時,可以設計一個適配器抽象類實現接口,并為接口中的每個方法提供默認方法,抽象類的子類就可以有選擇的覆蓋父類的某些方法實現需求,它適用于一個接口不想使用所有的方法的情況。在java8后,接口中可以有default方法,就不需要這種缺省適配器模式了。接口中方法都設置為default,實現為空,這樣同樣同樣可以達到缺省適配器模式同樣的效果。

圖示

缺省適配器模式結構圖:

適配器Adapter類實現Target接口,方法默認為空。

代碼示例

目標角色(SampleOperation.java):

public interface SampleOperation { public abstract void operation1(); public abstract void operation2(); public abstract void operation3(); public abstract void operation4(); public abstract void operation5();}

包含了很多操作。

適配器角色(DefaultAdapter.java):

public abstract class DefaultAdapter implements SampleOperation{ @Override public void operation1() { } @Override public void operation2() { } @Override public void operation3() { } @Override public void operation4() { } @Override public void operation5() { }}

默認實現了所有操作

這個是測試缺省適配器模式需要用到的類(Operator.java):

public class Operator { private SampleOperation sampleOperation; public void addOperation(SampleOperation sampleOperation) { this.sampleOperation = sampleOperation; } public void operation1() { sampleOperation.operation1(); } public void operation2() { sampleOperation.operation2(); } public void operation3() { sampleOperation.operation3(); } public void operation4() { sampleOperation.operation4(); } public void operation5() { sampleOperation.operation5(); }}

缺省適配器模式測試類(DefaultAdapterTest.java):

public class DefaultAdapterTest { public static void main(String[] args) { // 1、原來要實現所有操作類的操作 Operator operator1 = new Operator(); operator1.addOperation(new SampleOperation() { @Override public void operation1() {} @Override public void operation2() { System.out.println("操作2"); } @Override public void operation3() {} @Override public void operation4() {} @Override public void operation5() {} }); operator1.operation2(); // 2、使用缺省適配器只需要實現需要用到的接口方法 Operator operator2 = new Operator(); operator2.addOperation(new DefaultAdapter() { @Override public void operation2() { System.out.println("操作2"); } }); operator2.operation2(); }}

測試類需要執行操作2,operator1添加SampleOperation時要實現接口里所有方法,operator2添加SampleOperation時只需要通過DefaultAdapter適配器添加自己需要的操作即可。毫無疑問,測試結果是一樣的。

優點

1、復用性:系統需要使用已經存在的類,功能符合系統要求,但這個類的接口不符合系統的需求,通過適配器模式解決不兼容的問題,使這些功能類得到復用。

2、擴展性:適配器使得系統多了一個方式擴展系統的功能

3、耦合性:一定程度上的解耦

缺點

過多地使用適配器,增加系統理解難度。

總結

本文主要介紹了三種適配器模式,本質上是現有的不兼容的接口轉換為需要的接口。

類適配器模式,以繼承現有類的方式轉換。

對象適配器模式,以聚合對象實例的方式轉換。

接口適配器模式,以實現接口的方式轉換。

適配器模式是在現有的類和系統都不易修改的情況下使用,在系統設計之初慎用適配器模式。

2018年10月18日14:53:33

云南十一选五开奖结果