在現實世界中,如果想讓交流電220伏特的電源給直流12伏特的筆記本供電。我們會使用AC適配器。進行電流的轉化。在程序中也常常需要這樣的適配器。
在程序世界中,經常會有現有的程序無法直接使用,需要做適當的變換之後才能使用。
Adapter模式:用於填補“現有程序”和“所需程序”之間差異的設計模式。
Adapter模式有以下兩種:
1、類適配器模式(使用繼承的適配器)
2、對象適配器模式(使用委託的適配器)。
程序示例(1)(使用繼承的適配器)
package Class;
//現在是實際情況.220伏特的電源
public class Banner {
private String string;
public Banner(String string) {
this.string=string;
}
public void showWithParent() {
System.out.println("("+string+")");
}
public void showWithAster() {
System.out.println("*"+string+"*");
}
}
package Class;
//print接口。是“需求”的接口。12伏特的需求
public interface Print {
public abstract void printWeak();
public abstract void printStrong();
}
package Class;
//該類扮演適配器的角色。繼承類Banner類和裏面的方法。
//同時又實現了print接口
public class PrintBanner extends Banner implements Print {
public PrintBanner(String string) {
super(string);
}
public void printWeak() {
showWithParent();
}
public void printStrong() {
showWithAster();
}
}
package Class;
//通過扮演適配器覺得的printBanner類來弱化(帶括號)或者強化(帶星號)Hello字符串的顯示
public class Main {
public static void main(String[] args) {
Print print=new PrintBanner("Hello");
print.printWeak();
print.printStrong();
}
}
這裏將PrintBanner類實例保存在了Print類型的變量中,在Main類中,我們使用Print接口(即調用printWeak方法和printStrong方法)來進行編程的。對Main類代碼而言,Banner類、showWithParent方法和showWithAster方法被完全隱藏起來了。這就好像筆記本電腦只要在直流12伏特電壓下就能正常工作,但它並不知道12伏特的電壓是由適配器將220伏特電壓轉換而成的。
Main類並不知道PrintBanner類是如何實現的,這樣就可以不再對Main類進行修改的情況下改變PrintBanner類的具體實現。
注意使用接口類的使用原則。“不要使用具體類來編程,要優先使用抽象類和接口來編程”。
實例程序(2)(使用委託的示例程序)
關於委託:
委託:通俗來說就是“交給其他人”。在Java語言中,委託就是將某個方法中的實例處理交給其他實例的方法。(之前看到一篇文章寫的是C#的委託。裏面解釋的是C#中因爲沒有函數指針這個東西,所以使用了這個委託的形式。)
Main類和Banner類與示例1完全相同。不過這裏假設Print不是藉口而是類。
其實這裏的委託就是委託給了Bannner實例。而PrintBanner不再是繼承Bannner和實現Print接口。改成了繼承Print類。進而在程序中使用Banner的實例進行調用Bannner中的方法。
package Class;
//print接口。是“需求”的接口。12伏特的需求
public abstract class Print {
public abstract void printWeak();
public abstract void printStrong();
}
package Class;
//該類扮演適配器的角色。繼承類Banner類和裏面的方法。
//同時又實現了print接口
public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String string) {
this.banner=new Banner(string);
}
public void printWeak() {
banner.showWithParent();
}
public void printStrong() {
banner.showWithAster();
}
}
Adapter模式中的登場角色
在adapter模式中有以下登場角色
1、Target(對象)
該角色負責定義所需的方法。例:12伏特的直流電源電壓。在示例程序中,由Print接口和Print類扮演此角色。
2、Clinet(請求者)
該角色負責使用Target角色所定義的方法進行具體處理。例:直流12伏特驅動的筆記本。在示例程序中,由Main類扮演此角色。
3、Adaptee(被適配)
Adaptee是一個持有既定方法的角色。例:220伏特的交流電源。在程序示例中是Bannner。
如果Adaptee角色中方法與Target角色方法相同,就不需要接下來的Adapter角色了。
4、Adapter(適配器)
Adapter模式的主人公。使用Adapter角色的方法來滿足Target角色的需求,這是Adapter模式的目的,也就是Adapter角色的作用。在示例程序中是PrintBanner。
在類適配器模式中,Adapter角色通過集成來使用Adaptee角色。而在對象適配器模式中Adapter角色通過委託來使用Adapter角色。
拓展思路要點
1、什麼使用使用Adapter模式
Adapter模式會對現有類進行適配,生成新的類。通過該模式可以很方便地創建我們需要的方法羣。當出現bug的時候,由於我們很明確地知道了bug不在現有類(Adaptee角色)中,所以只需要扮演Adapter角色的類即可。這樣一來,代碼問題排查就會變得非常簡單。
2、如果沒有現成的代碼讓現有類適配新的接口時,使用Adapter模式似乎理所當然。不過實際上,我們在使用現有類適配新的接口時,常會有將這裏稍微修改一下就好了。但是如果對已測試的代碼進行修改,就必須重新進行測試。
使用Adapter模式可以在完全不改變現有代碼的前提下使用吸納有代碼適配接口。此外,在Adapter中並非需要知道現成代碼,只要知道類的功能,就可以編寫出新的類。
3、版本升級與兼容
在版本升級的時候常出席那“與舊版本兼容性”問題,現實中又不能完全拋棄舊版本。這是就可以使用Adapter模式使新舊版本兼容。幫助我們輕鬆的維護新版本與舊版本、
例如:今後只想維護新版本,就可以讓新版本扮演Adaptee的角色,舊版本扮演Target的角色。接着編寫Adapter角色的類,讓它使用新版本來實現舊版本的類的方法。
相關的模式
1、Bridge模式
Adapter模式用於連接接口不同的類,而Bridge模式則用於連接類的功能層次結構與實現層次結構。
2、Decorator模式
Adapter用於填補不用接口之間的縫隙,而Decorator,模式則是在不改變接口的前提下增加功能。