將一個接口轉換爲客戶但願的另外一個接口,使接口不兼容的那些類能夠一塊兒工做,別名爲包裝器。
適配器中的接口是廣義的接口,能夠表示一個方法或者方法的集合。java
適配器模式既能夠做爲類結構型模式,也能夠做爲對象結構型模式。ide
根據適配器與適配者類的關係不一樣,能夠分爲對象適配器模式以及類適配器模式。測試
對象適配器模式就是適配器與適配者之間是關聯關係。
結構圖以下:
spa
類適配器模式就是適配器與適配者之間是繼承或實現關係。
結構圖以下:
因爲語言特性的限制,好比Java,C#不支持多重繼承,類適配器模式受到不少限制,例如Target若是不是接口而是一個類,就沒法使用類適配器模式。此外若是適配者爲final
類也沒法使用適配器模式,在Java等語言中大部分狀況下使用對象適配器模式。設計
Target類以及實現了Target的類:code
interface Target { void request(); } class ConcreteTarget implements Target { @Override public void request() { System.out.println("具體Target方法"); } }
適配者類:對象
class Adaptee { public void specificRequest() { System.out.println("Adaptee方法"); } }
適配器類(實現了Target,適配者做爲成員變量):blog
class Adapter implements Target { private Adaptee adaptee = new Adaptee(); @Override public void request() { adaptee.specificRequest(); } }
測試:繼承
public class Test { public static void main(String[] args) { Target target = new ConcreteTarget(); target.request(); Target adapter = new Adapter(); adapter.request(); } }
在上述對象適配器的基礎上,適配者與Target保持不變,適配器繼承了適配者並實現了Target,同時取消了適配者做爲成員變量,在方法內直接調用super.xxx
,也就是適配者的方法:接口
class Adapter extends Adaptee implements Target { @Override public void request() { super.specificRequest(); } }
假設目前只有一條Micro USB線以及一臺只有Type-C接口的手機,須要對其進行充電,這時候就須要一個轉接頭把Micro USB轉爲Type-C接口,才能給手機充電。
這裏的Target就是Type-C,適配者就是Micro USB,適配器就是轉接頭,簡化實現代碼以下:
public class Test { public static void main(String[] args) { TypeC typeC = new MicroUSBToTypeC(); typeC.chargeWithTypeC(); } } //Target:給TypeC接口的手機充電 interface TypeC { void chargeWithTypeC(); } //Adaptee:適配者,MicroUSB線 class MicroUSB { public void chargeWithMicroUSB() { System.out.println("MicroUSB充電"); } } //Adapter:適配器,MicroUSB到TypeC的轉接頭 class MicroUSBToTypeC implements TypeC { private MicroUSB microUSB = new MicroUSB(); @Override public void chargeWithTypeC() { microUSB.chargeWithMicroUSB(); } }
在對象適配器的使用過程當中,若是在適配器中同時包含對Target類和Adaptee類的引用,Adaptee類能夠經過適配器調用Target類中的方法,Target類也能夠經過適配器調用Adaptee類的方法,那麼該適配器就是一個雙向適配器。例子以下:
public class Test { public static void main(String[] args) { Adapter adapter = new Adapter(); adapter.request(); adapter.specificRequest(); } } //適配者 interface Adaptee { void specificRequest(); } //Target類 interface Target { void request(); } //Target實現 class TargetImpl implements Target { @Override public void request() { System.out.println("Target方法"); } } //適配者實現 class AdapteeImpl implements Adaptee { @Override public void specificRequest() { System.out.println("Adaptee方法"); } } //適配器 class Adapter implements Adaptee,Target { private Target target = new TargetImpl(); private Adaptee adaptee = new AdapteeImpl(); @Override public void request() { //Target的方法調用適配者方法 adaptee.specificRequest(); } @Override public void specificRequest() { //適配者方法調用Target的方法 target.request(); } }
缺省適配器:當不須要實現一個接口所提供的全部方法時,可先設計一個抽象類實現該接口,併爲接口中的每一個方法都提供一個默認實現(空實現),那麼該抽象類子類能夠選擇性覆蓋父類的某些方法來實現需求,它適用於不想使用一個接口中全部方法的狀況,又叫單接口適配器模式。
Java AWT中通常能夠經過兩種方式來處理窗口事件:
WindowListener
WindowAdapter
其中WindowAdapter
實現了WindowListener
接口,可是都是提供了空實現,也就是說實現WindowsListener
的話須要實現裏面全部的方法,而繼承WindowAdapter
只須要選擇性地覆蓋方法便可,結構圖:
類適配器以及對象適配器的共同優勢以下:
類適配器的獨有優勢以下:
對象適配器的獨有優勢以下:
類適配器缺點:
final
類,C#的sealed
類對象適配器缺點: