1、意圖:
將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
2、場景描述:
手機的Usb數據線可以被看做適配器,不同類型的手機通過不同的Usb數據線連接到電腦相同的usb接口上。幾年前的非智能手機,數據線連接手機的一端由於手機品牌的不同使用了各式各樣的接口,但是連接電腦的一端卻采用了相同usb接口。針對特定品牌的數據線使得每種不同的手機都可以連接到電腦的usb接口上,使得手機接口可以與電腦的usb接口協同工作。
另外,C++中的棧(stack)、隊列(queue)被稱作容器適配器,它們本身都是基於線性表來實現的,但是對外提供了特定的操作接口,如stack的LIFO(last-in first-out)特性。
3、適配器模式類圖:
對象適配器類圖:
角色:
- Client:用戶類,使用新接口Target來完成某些特定的需求。
- Target:新的接口類,開放特定接口request來完成某些特定操作,與Client協作。
- Adaptee:原有的類。
- Adapter:適配器類,將Adaptee中的接口封裝成Target中的新接口,來滿足新的需求。
協作:
- Client調用Adapter實例的操作,Adapter使用Adaptee來完成這些被調用的操作。
注:
- 類圖中表示的是適配器模式兩種類圖中的對象適配器類圖,另外一種類適配器通過多重繼承兩個類或實現兩個接口來實現。
4、適用性:
- 使用一個原本存在的類來滿足新的需求,但是原來的類與新的需求類接口不一致。
- 希望復用原有的類,但是某些方法在原有的類中不存在,通過Adapter類來修改原來類Adaptee中的接口,並且添加Adaptee中不存在的方法。
5、實例類圖:
說明:
- UsbPort、PhonePort分別是電腦Usb端口、手機端口的類定義信息。
- Human的將手機連接到電腦的操作(linkPhoneToComputer)使用UsbDataLine來完成。
6、代碼實例:
手機端口類,含有手機端口的信息,對應適配器模式中的Adaptee。
1 package com.crazysnail.adapter; 2 3 public class PhonePort { 4 public void getPhonePort(){ 5 System.out.println("我是一個手機接口"); 6 } 7 }
Usb端口類,滿足將設備連接到電腦的新需求,對應適配器模式中的Target。
1 package com.crazysnail.adapter; 2 3 public class UsbPort { 4 public void getUsbPort(){ 5 System.out.println("我是一個usb接口"); 6 } 7 }
數據線類,一端連接到手機端口,開放數據線另一端的usb接口,對應適配器模式中的Adapter。
1 package com.crazysnail.adapter; 2 3 public class UsbDataLine extends UsbPort{ 4 private PhonePort phonePort; 5 6 public UsbDataLine() { 7 System.out.println("獲取一條匹配特性型號手機的數據線"); 8 phonePort = new PhonePort(); 9 } 10 11 @Override 12 public void getUsbPort(){ 13 phonePort.getPhonePort(); 14 System.out.println("手機接口連接到數據線一端,開放數據線的usb接口一端"); 15 } 16 }
人類類,有連接手機到電腦的需求,使用數據線將手機連接到電腦,對應適配器模式中的Client。
1 package com.crazysnail.adapter; 2 3 public class Human { 4 public static void linkPhoneToComputer(UsbDataLine line){ 5 line.getUsbPort(); 6 System.out.println("將Usb接口連接到電腦"); 7 } 8 }
測試類,效果演示。
1 package com.crazysnail.adapter; 2 3 public class AdapterTest { 4 public static void main(String[] args){ 5 UsbDataLine newUsbDataLine = new UsbDataLine(); 6 7 Human.linkPhoneToComputer(newUsbDataLine); 8 } 9 }
效果圖:
7、適配器模式的特點
- 實現了類的復用,利用了原有的Adaptee類,通過Adapter接口的包裝或改造,滿足了新需求。
- 當需要沖定義Adaptee類時,可能會影響到Adapter中的操作。