Java设计模式(六)----适配器模式
適配器模式
1、概述 2、適配器模式的用途 3、模式中的角色 4、實現方式 5、類適配器和對象適配器的權衡 6、缺省適配模式1、概述
適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
2、適配器模式的用途
即Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以在一起工作。
下面是兩個典型例子
3、模式中的角色
3.1 目標接口(Target):客戶所期待的接口。目標可以是具體的或抽象的類,也可以是接口。
3.2 需要適配的類(Adaptee):需要適配的類或適配者類。
3.3 適配器(Adapter):通過包裝一個需要適配的對象,把原接口轉換成目標接口。
4、實現方式
(1)類的適配器模式(采用繼承實現)
源代碼:
//目標接口,或稱為標準接口 public interface Target {//普通功能public void request(); }//已存在的、具有特殊功能、但不符合我們既有的標準接口的類 public class Adaptee {public void specificRequest() {System.out.println("被適配類...我是兩孔插座 具有特殊功能");} }//適配器類,繼承了被適配類,同時實現標準接口 public class Adapter extends Adaptee implements Target {@Overridepublic void request() {System.out.println("我是適配器類 我能適配任何兩孔插座 讓它正常工作");this.specificRequest();}}public class Client {public static void main(String[] args) {Target adapter = new Adapter(); //通過適配器調用特殊功能adapter.request(); } }結果:
我是適配器類 我能適配任何兩孔插座 讓它正常工作
被適配類…我是兩孔插座 具有特殊功能
(2)對象適配器(采用對象組合方式實現)
源代碼: //目標接口,或稱為標準接口 public interface Target {//普通功能public void request(); }//已存在的、具有特殊功能、但不符合我們既有的標準接口的類 public class Adaptee {public void specificRequest() {System.out.println("被適配類...我是兩孔插座 具有特殊功能");} } //適配器類,直接關聯被適配類,同時實現標準接口 class Adapter implements Target {// 直接關聯被適配類private Adaptee adaptee;// 可以通過構造函數傳入具體需要適配的被適配類對象public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {// 這里是使用委托的方式完成特殊功能System.out.println("我是適配器類 我能適配任何兩孔插座 讓它正常工作");this.adaptee.specificRequest();} }public class Client {public static void main(String[] args) {//使用特殊功能類,即適配類, // 需要先創建一個被適配類的對象作為參數 Target adapter = new Adapter(new Adaptee()); adapter.request(); } }結果:
我是適配器類 我能適配任何兩孔插座 讓它正常工作
被適配類…我是兩孔插座 具有特殊功能
從類圖中我們也知道需要修改的只不過就是 Adapter 類的內部結構,即 Adapter 自身必須先擁有一個被適配類的對象,再把具體的特殊功能委托給這個對象來實現。使用對象適配器模式,可以使得 Adapter 類(適配類)根據傳入的 Adaptee 對象達到適配多個不同被適配類的功能,當然,此時我們可以為多個被適配類提取出一個接口或抽象類。這樣看起來的話,似乎對象適配器模式更加靈活一點。
5、類適配器和對象適配器的權衡(摘自大牛博客)
● 類適配器使用對象繼承的方式,是靜態的定義方式;而對象適配器使用對象組合的方式,是動態組合的方式。
對于對象適配器,一個適配器可以把多種不同的源適配到同一個目標。換言之,同一個適配器可以把源類和它的子類都適配到目標接口。因為對象適配器采用的是對象組合的關系,只要對象類型正確,是不是子類都無所謂。
● 對于對象適配器,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實現重定義,然后讓適配器組合子類。雖然重定義 Adaptee的行為比較困難,但是想要增加一些新的行為則方便的很,而且新增加的行為可同時適用于所有的源。
● 對于類適配器,僅僅引入了一個對象,并不需要額外的引用來間接得到Adaptee。
● 對于對象適配器,需要額外的引用來間接得到Adaptee。
建議盡量使用對象適配器的實現方式,多用合成/聚合、少用繼承。當然,具體問題具體分析,根據需要來選用實現方式,最適合的才是最好的。
適配器模式的優點
更好的復用性
系統需要使用現有的類,而此類的接口不符合系統的需要。那么通過適配器模式就可以讓這些功能得到更好的復用。
更好的擴展性
在實現適配器功能的時候,可以調用自己開發的功能,從而自然地擴展系統的功能。
適配器模式的缺點
過多的使用適配器,會讓系統非常零亂,不易整體進行把握。比如,明明看到調用的是A接口,其實內部被適配成了B接口的實現,一個系統如果太多出現這種情況,無異于一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構。
6、缺省適配模式
缺省適配(Default Adapter)模式為一個接口提供缺省實現,這樣子類型可以從這個缺省實現進行擴展,而不必從原有接口進行擴展。作為適配器模式的一個特例,缺省是適配模式在JAVA語言中有著特殊的應用。
就是一個抽象類對功能接口的所有功能做空實現 然后子類繼承這個抽象類 這樣就可以對部分功能進行實現或拓展了
源代碼
功能接口:
/*** 功能接口 談戀愛后具備如下功能* 牽手* 接吻* 看電影* 情侶晚餐* 回家見父母* @author Administrator**/ public interface Love {//牽手 該功能是戀愛后經常會有的波public void hand();//接吻public void kiss();//看電影public void lookMovie();//情侶晚餐public void have();//回家見父母public void backHome();//女朋友是誰public String getGirlFriend();}缺省適配類
/*** 抽象類 * 交往類 實現戀愛接口* 哈哈 交往多了自然就談愛了嗎 嘻嘻嘻!* 但是交往畢竟不是談戀愛 雖然它具有了談戀愛的雛形 但是畢竟不是* 所以對談戀愛的所有功能做了空實現 只有架子* 相當于沒有 但是未來可能會有 嘎嘎嘎* @author Administrator**/ public abstract class Communication implements Love {//全是空實現 @Overridepublic void hand() {}@Overridepublic void kiss() {}@Overridepublic void lookMovie() {}@Overridepublic void have() {}@Overridepublic void backHome() {}@Overridepublic String getGirlFriend() {return null;}}具體實現
/*** 具體的類 湯高 繼承了交往Communication抽象類 * 本類湯高已經從交往慢慢戀愛了 所以它已經具備了談戀愛接口* 的所有功能 但是了 有些功能他每天不可能天天都調用* 比如 看電影 情侶晚餐 回家見父母等等 * (因為分隔兩地,不能天天見面 但是了 他們一見面就和過年一樣高興* 他們就可以調用戀愛中的一些功能* 比如他們 可以看電影 共進晚餐* )* * @author Administrator**/public class 湯高 extends Communication {//看電影public void lookMovie(){System.out.println("我們一起看電影 哈哈");}//情侶晚餐public void have(){System.out.println("我們一起吃晚餐 哈哈");}//女朋友是誰public String getGirlFriend(){return "周思遠";} }客戶端:
public class Client {public static void main(String[] args) {Love tanggao=new 湯高();tanggao.lookMovie();tanggao.have();System.out.println("女朋友是 :"+tanggao.getGirlFriend());} }結果:
我們一起看電影 哈哈
我們一起吃晚餐 哈哈
女朋友是 :周思遠
在很多情況下,必須讓一個具體類實現某一個接口,但是這個類又用不到接口所規定的所有的方法。通常的處理方法是,這個具體類要實現所有的方法,那些有用的方法要有實現,那些沒有用的方法也要有空的、平庸的實現。
這些空的方法是一種浪費,有時也是一種混亂。除非看過這些空方法的代碼,程序員可能會以為這些方法不是空的。即便他知道其中有一些方法是空的,也不一定知道哪些方法是空的,哪些方法不是空的,除非看過這些方法的源代碼或是文檔。
缺省適配模式可以很好的處理這一情況。可以設計一個抽象的適配器類實現接口,此抽象類要給接口所要求的每一種方法都提供一個空的 方法。就像具體幫助類湯高一樣 他只實現某一部分功能 因為他只用到了某一部分功能而已,如果以后要用,再實現其他功能就是,但是今天他不用,就沒必要該功能了!
適配器模式的用意是要改變源的接口,以便于目標接口相容。缺省適配的用意稍有不同,它是為了方便建立一個不平庸的適配器類而提供的一種平庸實現。
在任何時候,如果不準備實現一個接口的所有方法時,就可以使用“缺省適配模式”制造一個抽象類,給出所有方法的平庸的具體實現。這樣,從這個抽象類再繼承下去的子類就不必實現所有的方法了
以上內容來自平時所看書籍和網絡資源整理測試所得,如有不完善之處,歡迎指正!
總結
以上是生活随笔為你收集整理的Java设计模式(六)----适配器模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山石网科SG-6000-E5560配置S
- 下一篇: js中创建form表单