今天跟同事談起了一道面試題:「Proxy模式跟Adpater模式的區別」,這兩個設計模式都是很類似的模式,不少有點經驗的程序員均可能會聊的頭頭是道,可是恐怕談起一些設計上的細節可能就會卡殼,所以我寫下了這篇文章,以此做爲一個簡短的回顧。java
Adpater屬於兩種適應設計模式中的其中一種,另一種是Iterator(迭代器)模式,下次有機會再仔細聊聊它。程序員
設計模式的書很喜歡以‘電源適配器插頭’做爲適配器模式的範例範例,那麼咱們也從這個例子開始吧。面試
暴露給調用方的接口,定義了被適配對象暴露的方法。(咱們須要220V的電源)設計模式
實際須要使用接口的邏輯(某電器須要使用220V的電源)this
被適配者,包含了具體的實現,及可能不太合適調用方使用的方法。(110V的電源不合適如今所用的電器)spa
實際適配的實現,用繼承的方式隱藏了被適配對象的實現,又以實現適配接口的方式暴露調用者適合的方法。設計
下面的代碼實現了一個輸出110V的電源,經過220V電源適配器,實現了一個符合22V標準接口的輸出,提供給客戶端的示範。代理
# adpatee public class Power110v { private int volte = 110; public Power110v(){ System.out.print("the power is on at "+volte+"V"); } public String get100vPower(){ return volte; } } # target public interface Power220v { get220vPower(String input); } # adapter public PowerAdpater extends Power110v implemnts Power220v { public get220vPower(){ volte = volte * 2; System.out.println("the power is on at "+volte+"V") } } #client public class Main (){ public static void main(String[] args){ PowerAdapter pa = new PowerAdapter(); pa.get220vPower(); } }
Adapter模式適用於那些已有代碼很穩定,但新調用方須要對部分代碼進行調整,或者組合多個方法進行組合實現邏輯的狀況下適用。能夠儘可能適用已有的穩定代碼,只做適當的修改即可以完成新的邏輯功能。code
使用proxy的角色,功能的調用方,下面的例子是Manager(經理)類。對象
定義了proxy角色與RealSubject的一致性接口,範例代碼中,是Reportable(可彙報)接口,
Proxy會處理來自Client的請求,能夠處理的功能本身處理,不能處理的功能讓RealSubject處理,範例代碼是TeamLeader類。
RealSubject將會在Proxy缺少功能時提供實現,跟Proxy同樣實現一樣的接口,範例代碼中是TeamMember類。
public interface Reportable{ public void setReportMatrial(String jobContent); public String getReportMatrial(); public String getFeedback(); } public TeamMember implements Reportable{ String reportMatrial; public void setReportMatrial(String input){ this.reportMatrial = input; } public String getReportMatrial(){ return this.reportMatrial; } public String getFeedback(){ return "Here is the report content ["+this.reportMatrial+"]"; } } } public TeamLeader implements Reportable{ String reportMatrial; TeamMember member; public TeamLeader(String input){ this.reportMatrial = input; } public void setReportMatrial(String input){ if (member != null){ member.setReportMatrial(input) } this.reportMatrial = input; } public String getReportMatrial(){ return this.reportMatrial; } public String getFeedback(){ if ( member != null ){ return member.getFeedback(); } member = new TeamMember(); member.setReportMatrial(this.reportMatrial); } } public class Manager { public static void main(String[] args){ TeamLeader tl = new TeamLeader("monthly report"); tl.setReportMatrial("weekly report") String currentReportType = tl.getReportMatrial(); // the manager forgot what kind report should receive System.out.println("the current report type is " + currentReportType); // the manager ask the teamleader for the report detail. System.out.println("get some report from team leader"tl.getFeedback()); } }
二者頭經過實現接口暴露實際邏輯給調用方,核心邏輯都在最內一層的類中。
Proxy實現subject類與proxy類,都是實現同樣的接口,暴露同樣的方法。Adpater模式則Adpater與Adpatee則不必定實現一樣的方法。理論上Proxy模式的proxy類,也承擔一部分的功能,當它沒法實現調用功能時纔會建立被代理的RealSubject類。Adpater類則原則上與Adpatee共存亡。