C#設計模式——適配器模式
一、適配器模式介紹:
由於應用環境的變化,我們需要的實現在新的環境中沒有現存對象可以滿足,但是其他環境卻存在這樣現存的對象。適配器模式將“將現存的對象”在新的環境中進行調用,使得新環境中不需要去重復實現已經存在了的實現而很好地把現有對象(指原來環境中的現有對象)加入到新環境來使用。適配器模式有類的適配器模式和對象的適配器模式兩種形式。
二、實現思維:
在適配器模式中,適配器可以是抽象類,並適配器模式的實現是非常靈活的,我們完全可以將Adapter模式中的“現存對象”作為新的接口方法參數,適配器類可以根據參數參數可以返回一個合適的實例給客戶端。把一個類的接口變換成客戶端所期待的另一種接口,從而使原本接口不匹配而無法一起工作的兩個類能夠在一起工作。
三、類的適配器模式:
四、對象適配器情景例子:
在當今社會手機已經是人們生活中必不可少的東西,就像人要吃飯,手機當然也要充電,相信很多蘋果手機用戶都遇到過手機沒電時沒帶充電線,找別人借卻只有安卓的充電線,這就很尷尬了。那麽如何用適配器模式解決這個問題呢?讓我們來看看下面的代碼。
五、對象適配器相關代碼:
1、創建適配器類——安卓插頭
/// <summary> /// 適配器模式中的源角色,需要適配的類,安卓插頭 /// </summary> public abstract class AndroidPlug { public voidSpecificRequest() { Console.WriteLine("我是安卓插頭"); } }
2、創建蘋果插頭的接口:
/// <summary> /// 適配器模式中的目標角色,蘋果插頭 /// </summary> public interface IApplePlug { void Request(); }
3、創建適配器類,提供蘋果插頭,實現安卓插頭方法:
/// <summary> /// 適配器類,提供蘋果插頭行為,但本質是調用安卓插頭方法/// </summary> public class AdapterPlug : AndroidPlug, IApplePlug { /// <summary> /// 實現安卓插頭方法 /// </summary> public void Request() { //調用安卓插頭方法 this.SpecificRequest(); } }
4、調用
static void Main(string[] args) { //現在可以通過適配器使用安卓插頭了 IApplePlug apple_plug = new AdapterPlug(); apple_plug.Request(); Console.ReadKey(); }
從上面代碼中可以看出,我們調用Request方法(即蘋果插頭),但是我們現有的類(即安卓插頭)並沒有Request方法,它只有SpecificRequest方法(即安卓插頭本身的方法),然而適配器類(適配器必須實現蘋果插頭接口和繼承安卓插頭類)可以提供這種轉換,它提供了Request方法的實現(其內部調用的是安卓插頭,因為適配器只是一個外殼罷了,包裝著安卓插頭,並向外界提供蘋果插頭的外觀,)以供我們使用。這可以結合現有的蘋果安卓一體充電線實體理解。
六、對象適配器:
既然現在適配器類不能繼承AndroidPlug抽象類了(因為用繼承就屬於類的適配器了),但是適配器類無論如何都要實現Request方法,所以一定是要繼承ApplePlug抽象類或IApplePlug接口的,然而適配器類的Request方法又必須調用AndroidPlug的SpecificRequest方法,又不能用繼承,這時候就想,不能繼承,但是我們可以在適配器類中創建AndroidPlug對象,然後在Requst中使用AndroidPlug的方法了。
七、對象適配器相關代碼:
1、創建源角色,安卓插頭類
/// <summary> /// 適配器模式的源角色,需要適配的類,安卓插頭 /// </summary> public class AndroidPlug { public void SpecificRequest() { Console.WriteLine("我是安卓插頭"); } }
2、創建目標角色,蘋果插頭類:
/// <summary> ///適配器模式中的目標角色,蘋果插頭 /// </summary> public class ApplePlug { // 客戶端需要的方法 public virtual void Request() { // 可以把一般實現放在這裏 } }
3、創建適配器類:
/// <summary> /// 適配器類,這裏適配器類沒有AndroidPlug類,而是引用了AndroidPlug對象,所以是對象的適配器模式的實現 /// </summary> public class Adapter : ApplePlug { // 引用安卓插頭的實例,從而將客戶端與AndroidPlug系起來 public AndroidPlug android_plug_Adapter = new AndroidPlug(); /// <summary> /// 實現蘋果插頭接口方法 /// </summary> public override void Request() { android_plug_Adapter.SpecificRequest(); } }
4、調用
static void Main(string[] args) { // 現在可以通過適配要使用安卓插頭了 ApplePlug apple_plug = new Adapter(); apple_plug.Request(); Console.ReadLine(); }
八、使用情景:
- 系統需要復用現有類,而該類的接口不符合系統的需求
- 想要建立一個可重復使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
- 對於對象適配器模式,在設計裏需要改變多個已有子類的接口,如果使用類的適配器模式,就要針對每一個子類做一個適配器,而這不太實際。
九、總結:
類的適配器模式:
優點:
- 可以在不修改原有代碼的基礎上來復用現有類,很好地符合開閉原則。
- 可以重新定義Adaptee(被適配的類)的部分行為,因為在類適配器模式中,Adapter是Adaptee的子類
- 僅僅引入一個對象,並不需要額外的字段來引用Adaptee實例(這個即是優點也是缺點)。
缺點:
- 用一個具體的Adapter類對Adaptee和Target進行匹配,當如果想要匹配一個類以及所有它的子類時,類的適配器模式就不能勝任了。因為類的適配器模式中沒有引入Adaptee的實例,光調用this.SpecificRequest方法並不能去調用它對應子類的SpecificRequest方法。
- 采用了 “多繼承”的實現方式,帶來了不良的高耦合。
對象的適配器模式
優點:
- 可以在不修改原有代碼的基礎上來復用現有類,很好地符合開閉原則
- 采用 “對象組合”的方式,更符合松耦合。
缺點:
- 使得重定義Adaptee的行為較困難,這就需要生成Adaptee的子類並且使得Adapter引用這個子類而不是引用Adaptee本身。
C#設計模式——適配器模式