1、什麼是適配器模式java
適配器這個詞咱們應該很熟悉,每天都在使用,手機充電時,電源線頭頭就叫電源適配器,幹什麼用的呢?把220V電壓轉換成手機充電時使用的電壓,那麼適配器是否是很好理解了,下面看一下定義。ide
Adapter適配器模式,將一個類的接口轉換成客戶但願的另一個接口。使本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做了。測試
適配器模式有「類適配器」和「對象適配器」兩種不一樣的形式。this
2、類適配器spa
經過繼承進行適配(類間繼承)。URL結構圖以下:翻譯
一、Target設計
Target目標角色,該角色定義把其它類轉換成指望接口,一般狀況下是一個接口或一個抽象類,通常不會是實現類。3d
public interface Target { public void request(); }
二、Adapteecode
Adaptee源角色,想把誰轉換爲目標角色,這個「誰」就是源角色,它是已經存在的、運行良好的類或對象。對象
public class Adaptee { public void specificRequest() { System.out.println("特殊請求"); } }
三、Adapter
Adapter適配器角色,是適配器模式的核心角色,它的職責是經過繼承或類關聯的方式把源角色轉換成目標角色。
public class Adapter extends Adaptee implements Target { @Override public void request() { super.specificRequest(); } }
四、ConcreteTarget
package designMode.adapter.sxn; public class ConcreteTarget implements Target { @Override public void request() { System.out.println("普通請求"); } }
五、測試類
package designMode.adapter.sxn; public class Client { public static void main(String[] args) { //原有業務邏輯 Target target = new ConcreteTarget(); target.request(); //增長適配器後的業務邏輯 Target target2 = new Adapter(); target2.request(); } }
六、輸出結果:
3、對象適配器
經過對象層次的關聯關係進行委託(對象的合成關係/關聯關係)。UML結構圖以下:
一、Target
客戶所期待的接口。目標能夠是具體的或抽象的類,也能夠是接口。
package designMode.adapter.sxn; public class Target { public void request() { System.out.println("普通請求"); } }
二、Adaptee
須要適配的類。
package designMode.adapter.sxn; public class Adaptee { public void specificRequest() { System.out.println("特殊請求"); } }
三、Adapter
經過在內部包裝一個Adaptee對象,把源接口轉換成目標接口。
package designMode.adapter.sxn; public class Adapter extends Target{ private Adaptee adaptee = new Adaptee(); @Override public void request() { adaptee.specificRequest(); } }
四、測試類
package designMode.adapter.sxn; public class Client { public static void main(String[] args) { Target target = new Adapter(); target.request(); } }
五、輸出結果
4、適配器模式的應用
一、什麼時候使用
(1)系統須要使用現有的類,從而類的接口不符合系統的須要。
(2)想創建一個能夠重複使用的類,用於一些彼此之間沒有太大關聯的一些類。
(3)經過接口轉換,將一個類插入另外一個類中。
二、方法
繼承或依賴。
三、優勢
(1)可讓任何兩個沒有關聯的類一塊兒運行。
(2)增長了類的透明性。
咱們訪問target目標角色,但具體實現都委託給了源角色,而這些對高層模塊是透明的,也是不須要關心的。
(3)提升了類的複用度。
源角色在原有的系統中仍是能夠正常使用,而在目標角色中也能夠充當新的演員。
(4)靈活性很是好。
何時不想要適配器了,直接刪掉就能夠了。
四、缺點
(1)過多使用適配器會使系統很是凌亂。
(2)因爲java是單繼承的,因此只能適配一個適配器類,並且目標類必須是抽象的。
五、注意事項
只有碰到沒法改變原有設計和代碼的狀況下,纔會考慮適配器模式。
5、適配器模式的實現
下面咱們以翻譯官爲例,姚明剛去美國時,不懂英文,專門爲他配備了翻譯,特別是在比賽場上,教練、隊員與他的對話所有都經過翻譯來溝通,這裏翻譯就是適配器。如今編寫一個適配器模式的例子,火箭隊比賽,教練叫暫停時給後衛、中鋒、前鋒分配進攻和防守任務。UML圖以下:
一、Player類
抽象球員類,有進攻和防守兩種方法。
package designMode.adapter; public abstract class Player { protected String name; public Player(String name) { this.name = name; } public abstract void attack(); //進攻 public abstract void defense(); //防守 }
二、前鋒、中鋒、後衛類
重寫了Player類中的進攻和防守兩個方法,此時是英文的,還沒有翻譯。
package designMode.adapter; public class Forwards extends Player{ public Forwards(String name) { super(name); } @Override public void attack() { System.out.println("Forward " + name + " attack"); } @Override public void defense() { System.out.println("Forward " + name + " defense"); } }
package designMode.adapter; public class Guards extends Player { public Guards(String name) { super(name); } @Override public void attack() { System.out.println("Forward " + name + " attack"); } @Override public void defense() { System.out.println("Forward " + name + " defense"); } }
三、ForeignCenters類
外籍中鋒類。只能聽懂中文。
package designMode.adapter; public class ForeignCenters { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void attackChi() { System.out.println("中鋒 " + name + " 進攻"); } public void defenseChi() { System.out.println("中鋒 " + name + " 防守"); } }
四、Translator類
翻譯者類,也就是適配器。對英文的進攻和防守進行翻譯。
package designMode.adapter; public class Translator extends Player{ private ForeignCenters foreignCenter = new ForeignCenters(); public Translator(String name) { super(name); foreignCenter.setName(name); } @Override public void attack() { foreignCenter.attackChi(); } @Override public void defense() { foreignCenter.defenseChi(); } }
五、測試類
package designMode.adapter; public class Client { public static void main(String[] args) { Player bPlayer = new Forwards("杜蘭特"); bPlayer.attack(); Player mPlayer = new Guards("麥克格雷迪"); mPlayer.attack(); Player yPlayer = new Translator("姚明"); yPlayer.attack(); yPlayer.defense(); } }
六、運行結果
6、類適配器和對象適配器的區別
從上面的內容能夠看出,類適配器是類間繼承,對象適配器是對象的合成關係,也能夠說是類的關聯關係,這是二者的根本區別。
因爲對象適配器是經過類間的關聯關係進行耦合的,所以在設計時就能夠作到比較靈活,而類適配器就只能經過覆寫源角色的方法進行擴展。
在實際項目中,對象適配器使用的場景較多。
每一篇博客都是一種經歷,程序猿生涯的痕跡,知識改變命運,命運要由本身掌控,願你遊歷半生,歸來還是少年。
欲速則不達,欲達則欲速!
更多精彩內容,首發公衆號【素小暖】,歡迎關注。