一、概述 適配器模式將一個類的介面,轉換為客戶期望的另一個介面。適配器讓原本不相容的類可以合作無間 二、解決問題 從模式的定義中,我們看到適配器模式就是用來轉換介面,解決不相容問題的。想想我們現實生活中的適配器,最常用的就是手機充電器了,也叫做電源適配器,它把家用交流強電轉換為手機用的直流弱電。其中 ...
一、概述
適配器模式將一個類的介面,轉換為客戶期望的另一個介面。適配器讓原本不相容的類可以合作無間
二、解決問題
從模式的定義中,我們看到適配器模式就是用來轉換介面,解決不相容問題的。想想我們現實生活中的適配器,最常用的就是手機充電器了,也叫做電源適配器,它把家用交流強電轉換為手機用的直流弱電。其中交流電就是被適配者,充電器是適配器,手機是用電客戶。
三、結構類圖
四、成員角色
客戶(Client):只能調用目標介面功能,不能直接使用被適配器,但可以通過適配器的介面轉換間接使用被適配器。
目標介面(Target):客戶看到的介面,適配器必須實現該介面才能被客戶使用。
適配器(Adapter):適配器把被適配者介面轉換為目標介面,提供給客戶使用。
被適配者(Adaptee):被適配者介面與目標介面不相容,需要適配器轉換成目標介面子類,才能被客戶使用。
五、應用實例
下麵用鳥叫和鳥飛的例子解析適配器模式,鸚鵡會叫也會飛,但鵝就只會叫不會飛,而且鵝也不是鳥類,我們要創建一個適配器,把鵝轉換成鳥。
第一步、創建鳥介面,對應角色目標介面
package adapter.pattern; //鳥介面 public interface Bird { //鳥叫 public void chirp(); //飛 public void fly(); }
第二步、創建鸚鵡類
package adapter.pattern; //鸚鵡類實現鳥介面 public class Parrot implements Bird{ public void chirp() { System.out.println("嗚嗚嗚"); } public void fly() { System.out.println("我能飛很遠很遠"); } }
第三步、創建鵝類,對應角色被適配者
package adapter.pattern; //鵝類,不是鳥 public class Goose { //鵝會叫但不會飛,沒有飛的方法 public void chirp(){ System.out.println("嘎嘎嘎"); } }
第四步、創建適配器
package adapter.pattern; //適配器,把鵝類適配為鳥 public class GooseAdapter implements Bird{ //組合鵝類 Goose goose; public GooseAdapter(Goose goose){ this.goose = goose; } public void chirp() { if(goose != null){ //調用鳥叫的時候委托鵝叫 goose.chirp(); } } public void fly() { //不支持該操作,可以拋出該異常,客戶可以知道詳情 throw new UnsupportedOperationException(); } }
第五步、測試適配器
package adapter.pattern; public class AdapterTest { public static void main(String[] args){ System.out.println("-----鸚鵡會叫也會飛-----"); Bird parrot = new Parrot(); parrot.chirp(); parrot.fly(); System.out.println("-----鵝會叫但不會飛-----"); Goose goose = new Goose(); Bird gooseAdapter = new GooseAdapter(goose); gooseAdapter.chirp(); gooseAdapter.fly(); } }
運行結果:
適配器在java中的例子,我們知道ArrayList類實現了迭代器(Iterator),但不支持枚舉(Enumeration),下麵我們就來實現ArrayList的枚舉操作。
package adapter.pattern; import java.util.ArrayList; import java.util.Enumeration; public class ItertorEnumeration implements Enumeration{ //組合被適配者 private ArrayList<String> list; //集合的計數器,判斷指針指向集合的位置 private int index = 0; public ItertorEnumeration(ArrayList<String> list){ this.list = list; } public boolean hasMoreElements() { if(list != null && list.size() > index){ return true; } return false; } public Object nextElement() { String content = list.get(index); index++; return content; } }
六、優點和缺點
1、優點
(1)、轉換介面,適配器讓不相容的介面變成相容。
(2)、讓客戶和實現的介面解耦。有了適配器,客戶端每次調用不相容的介面時,不用修改自己的代碼,只要調用適合的適配器就可以了。
(3)、使用了對象組合設計原則。以組合的方式包裝被適配者,被適配者的任何子類都可以搭配著同一個適配器使用。
(4)、體現了“開閉”原則。適配器模式把客戶和介面綁定起來,而不是和具體實現綁定,我們可以使用多個配適器來轉換多個後臺類,也可以很容易地增加新的適配器。
2、缺點
(1)、每個被適配者都需要一個適配器,當適配器過多時會增加系統複雜度,降低運行時的性能。
(2)、實現一個適配器可能需要下一番功夫,增加開發的難度。
七、使用場景
1、當要使用的兩個類所做的事情相同或者相似,但是具有不同的介面時考慮使用配適器模式。
2、當需要統一客戶端調用介面的代碼,而所調用的介面具有不相容問題時使用適配器模式。這樣客戶端只有調用一個介面就行了,這樣可以更簡單、更直接、更緊湊。
八、總結
1、適配器有對象適配器和類適配器,類適配器需要用到多重繼承。
2、適配器就是轉換介面達到我們的需要。