本文博客同步發(fā)表在 http://hjxandhmr.github.io/2016/06/02/DesignPattern-Adapter/
今天我們來學(xué)習(xí)一種結(jié)構(gòu)型模式赫模,適配器模式(Adapter Pattern)问顷。
模式定義
將一個接口轉(zhuǎn)換成客戶希望的另一個接口疮跑,適配器模式使接口不兼容的那些類可以一起工作瞄勾,其別名為包裝器(Wrapper)稀余。適配器模式有兩種,一種是對象適配器勘伺,一種是類適配器怠褐。
模式結(jié)構(gòu)
適配器模式包含如下角色:
Target: 目標抽象類
Adapter: 適配器類
Adaptee: 適配者類
Client: 客戶類
UML圖
類適配器UML圖
對象適配器UML圖
類適配器模式代碼實現(xiàn)
Target.java
public interface Target {
void sampleOperation1();
void sampleOperation2();
}
Adaptee.java
public class Adaptee {
public void sampleOperation1() {
System.out.println("sampleOperation1");
}
}
Adapter.java
public class Adapter extends Adaptee implements Target {
@Override
public void sampleOperation2() {
System.out.println("sampleOperation2");
}
}
測試類
public class MyClass {
public static void main(String[] args) {
Adapter adapter = new Adapter();
adapter.sampleOperation1();
adapter.sampleOperation2();
}
}
運行結(jié)果
對象適配器代碼實現(xiàn)
Target.java
public interface Target {
void sampleOperation1();
void sampleOperation2();
}
Adaptee.java
public class Adaptee {
public void sampleOperation1() {
System.out.println("sampleOperation1");
}
}
Adapter.java
public class Adapter implements Target {
private Adaptee mAdaptee;
public Adapter(Adaptee adaptee) {
mAdaptee = adaptee;
}
@Override
public void sampleOperation1() {
mAdaptee.sampleOperation1();
}
@Override
public void sampleOperation2() {
System.out.println("sampleOperation2");
}
}
測試類
public class MyClass {
public static void main(String[] args) {
Adapter adapter =new Adapter(new Adaptee());
adapter.sampleOperation1();
adapter.sampleOperation2();
}
}
運行結(jié)果
模式分析
類適配器使用對象繼承的方式,是靜態(tài)的定義方式闸婴;而對象適配器使用對象組合的方式坏挠,是動態(tài)組合的方式。
對于類適配器邪乍,由于適配器直接繼承了Adaptee降狠,使得適配器不能和Adaptee的子類一起工作,因為繼承是靜態(tài)的關(guān)系庇楞,當適配器繼承了Adaptee后榜配,就不可能再去處理 Adaptee的子類了。
對于對象適配器吕晌,一個適配器可以把多種不同的源適配到同一個目標蛋褥。換言之,同一個適配器可以把源類和它的子類都適配到目標接口睛驳。因為對象適配器采用的是對象組合的關(guān)系烙心,只要對象類型正確,是不是子類都無所謂乏沸。
對于類適配器淫茵,適配器可以重定義Adaptee的部分行為,相當于子類覆蓋父類的部分實現(xiàn)方法蹬跃。
對于對象適配器匙瘪,要重定義Adaptee的行為比較困難,這種情況下蝶缀,需要定義Adaptee的子類來實現(xiàn)重定義丹喻,然后讓適配器組合子類。雖然重定義Adaptee的行為比較困難扼劈,但是想要增加一些新的行為則方便的很驻啤,而且新增加的行為可同時適用于所有的源。
對于類適配器荐吵,僅僅引入了一個對象骑冗,并不需要額外的引用來間接得到Adaptee赊瞬。
對于對象適配器,需要額外的引用來間接得到Adaptee贼涩。
建議盡量使用對象適配器的實現(xiàn)方式巧涧,多用合成/聚合、少用繼承遥倦。當然谤绳,具體問題具體分析,根據(jù)需要來選用實現(xiàn)方式袒哥,最適合的才是最好的缩筛。
適配器模式的優(yōu)點
將目標類和適配者類解耦,通過引入一個適配器類來重用現(xiàn)有的適配者類堡称,而無須修改原有代碼瞎抛。
增加了類的透明性和復(fù)用性,將具體的實現(xiàn)封裝在適配者類中却紧,對于客戶端類來說是透明的桐臊,而且提高了適配者的復(fù)用性。
靈活性和擴展性都非常好晓殊,通過使用配置文件断凶,可以很方便地更換適配器,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器類巫俺,完全符合“開閉原則”认烁。
類適配器模式還具有如下優(yōu)點:
- 由于適配器類是適配者類的子類,因此可以在適配器類中置換一些適配者的方法识藤,使得適配器的靈活性更強砚著。
對象適配器模式還具有如下優(yōu)點:
- 一個對象適配器可以把多個不同的適配者適配到同一個目標,也就是說痴昧,同一個適配器可以把適配者類和它的子類都適配到目標接口稽穆。
適配器模式的缺點
類適配器模式的缺點如下:
- 對于Java、C#等不支持多重繼承的語言赶撰,一次最多只能適配一個適配者類舌镶,而且目標抽象類只能為抽象類,不能為具體類豪娜,其使用有一定的局限性餐胀,不能將一個適配者類和它的子類都適配到目標接口。
對象適配器模式的缺點如下:
- 與類適配器模式相比瘤载,要想置換適配者類的方法就不容易否灾。如果一定要置換掉適配者類的一個或多個方法,就只好先做一個適配者類的子類鸣奔,將適配者類的方法置換掉墨技,然后再把適配者類的子類當做真正的適配者進行適配惩阶,實現(xiàn)過程較為復(fù)雜。
參考
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/adapter.html
http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html
歡迎大家關(guān)注我的微信公眾號扣汪,我會不定期的分享些Android開發(fā)的技巧
[站外圖片上傳中……(5)]