設計模式(一)適配器模式
一、作用
適配器模式(Adapter):將一個類的接口轉換成客戶希望的另外一個接口,使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
二、適用場景
1. 業(yè)務的接口與工作的類不兼容,(比如:類中缺少實現(xiàn)接口的某些方法)但又需要兩者一起工作
2. 在現(xiàn)有接口和類的基礎上為新的業(yè)務需求提供接口
三、常見的使用方式
還是以Usb接口和Phone手機類的產品舉例子,假設設計的Phone類中有 call(), sms(), takeAlong()屬性方法,而在設計Usb接口時定義了 store(), takeAlong()的行為。如果現(xiàn)在有新的業(yè)務需求,需要生成 Xiaomi手機類具有 Phone類和Usb接口兩者功能,假設Phone類和Usb接口已經在業(yè)務上投入使用,很顯然,去修改原類中的方法和接口的行為去滿足現(xiàn)在的新業(yè)務需求是不可取的,那么現(xiàn)在適配者模式就派上用場了。
(1)類適配模式
大致的意思是新的業(yè)務類Xiaomi通過繼承舊業(yè)務的類Phone并實現(xiàn)接口Usb來滿足新的業(yè)務的一種適配方式,如下圖

Usb接口
1 public interface Usb { 2 3 void store(); 4 5 void takeAlong(); 6 }
Phone類
1 public class Phone { 2 3 public void call() { 4 System.out.println("Phone call"); 5 } 6 7 public void sms() { 8 System.out.println("Phone sms"); 9 } 10 11 public void takeAlong() { 12 System.out.println("Phone takeAlong"); 13 } 14 }
適配 Xiaomi 類
1 /** 2 * 類的適配器模式 3 * phone + Usb 4 * 將Phone的功能擴展到Usb里 5 6 */ 7 public class Xiaomi extends Phone implements Usb { 8 9 @Override 10 public void store() { 11 // TODO Auto-generated method stub 12 System.out.println("store implements usb"); 13 } 14 15 }
適配完后使用
1 Xiaomi mi1 = new Xiaomi(); 2 mi1.takeAlong(); 3 mi1.store();
輸出:
Phone takeAlong
store implements usb
這樣新的業(yè)務需求就可以通過適配的 Xiaomi類去滿足了。是不是覺得很簡單呢!!:) 有沒有其他的方式去實現(xiàn)同樣的功能呢?當然有,就是下面要講的對象適配模式。
(2)對象適配模式
實現(xiàn)的方式很簡單,其實就是在適配的時候通過構造函數(shù)將舊的業(yè)務Phone 當作新的適配類(XiaomiWrapper)一個成員對象去處理,然后適配類只需要實現(xiàn)接口 Usb即可。如下類關系圖

適配類XiaomiWrapper如下,注意takeAlong()方法,是直接調用原類對象(Phone)去執(zhí)行的。
1 public class XiaomiWrapper implements Usb { 2 3 /** 4 * 1.創(chuàng)建一個Wrapper類,持有原類的一個實例, 5 * 2.在Wrapper類的方法中,調用實例的方法就行 6 */ 7 private Phone phone; 8 9 public XiaomiWrapper(Phone phone) { 10 11 this.phone = phone; 12 } 13 14 @Override 15 public void store() { 16 // TODO Auto-generated method stub 17 System.out.println("store implements usb"); 18 19 } 20 21 @Override 22 public void takeAlong() { 23 // TODO Auto-generated method stub 24 phone.takeAlong(); 25 } 26 27 }
適配完后通過構造函數(shù)將原對象傳入即可。
1 XiaomiWrapper mi2 = new XiaomiWrapper(new Phone()); 2 mi2.takeAlong(); 3 mi2.store();
輸出:
Phone takeAlong
store implements usb
或許到這里,你會覺得這種方式很簡單吧。但是如果出現(xiàn)這個Usb接口中有很多方法(大于2個),但是新的業(yè)務需求中也只需要其中的一兩個,而且是需要適配很多這樣的業(yè)務,這樣的話,用上面的方法每次適配一次就會去實現(xiàn)所有Usb接口中的方法,實際上適配的類中有很多是用不到的,沒有必要把接口中不使用的類也適配進去,這時候,就輪到下面的接口適配模式出場了。
(3)接口適配模式
適配新的業(yè)務需求的時候借助抽象實現(xiàn)類(AbsPhone實現(xiàn)Usb接口),也就說,抽象實現(xiàn)類把Usb接口中的行為都實現(xiàn)了,新的適配是需要跟抽象類對話就行,因為抽象實現(xiàn)類就能滿足了所有適配的需求,并且做到了只適配業(yè)務本身的行為,接口中不需要的行為我根本不需要關注。這就是抽象實現(xiàn)類的作用。類圖關系如下:

抽象類AbsPhone實現(xiàn)
1 /** 2 * 接口的適配器模式 3 * 1.借助于一個抽象類,該抽象類實現(xiàn)了該接口,實現(xiàn)了所有的方法 4 * 2.繼承類可以選擇性的實現(xiàn)接口中的方法 5 */ 6 public abstract class AbsPhone implements Usb { 7 8 public void store() { 9 System.out.println("AbsPhone implements usb's store methond"); 10 } 11 12 public void takeAlong() { 13 System.out.println("AbsPhone implements usb's takeAlong methond"); 14 } 15 }
適配類只跟AbsPhone打交道,根本不需要關心接口的行為,只顯示自己所要關注的。
如Phone1適配只需要store()行為
1 public class Phone1 extends AbsPhone { 2 3 public void call() { 4 System.out.println("Phone1 call"); 5 } 6 7 public void sms() { 8 System.out.println("Phone1 sms"); 9 } 10 11 public void store() { 12 System.out.println("Phone1 need usb's store methond"); 13 } 14 15 }
Phone2適配只需要takeAlong()行為
1 public class Phone2 extends AbsPhone { 2 3 public void call() { 4 System.out.println("Phone2 call"); 5 } 6 7 public void sms() { 8 System.out.println("Phone2 sms"); 9 } 10 11 public void takeAlong() { 12 System.out.println("Phone2 need usb's takeAlong methond"); 13 } 14 15 }
實例化調用
1 Phone1 p1 = new Phone1(); 2 Phone2 p2 = new Phone2(); 3 p1.store(); 4 p2.takeAlong();
輸出:
Phone1 need usb's store methond
Phone2 need usb's takeAlong methond
來一次完整的調用
1 Phone1 p1 = new Phone1(); 2 Phone2 p2 = new Phone2(); 3 p1.store(); 4 p1.takeAlong(); 5 p2.takeAlong(); 6 p2.store();
輸出:
Phone1 need usb's store methond
AbsPhone implements usb's takeAlong methond
Phone2 need usb's takeAlong methond
AbsPhone implements usb's store methond
這樣很清晰的知道適配的什么方法了。
總結:適配者模式在android源碼中有很多這樣的體現(xiàn),大家看完這個再去看源碼,是不是會感覺看懂了不少呢?
浙公網安備 33010602011771號