设计模式笔记(7)---适配器模式(结构型)
Gof定義
將一個類的接口轉換成客戶所希望的另一個接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
動機
在軟件系統中,由于應用環境的變化,常常要將“一些現存的對象”放在心的環境中應用,但是新環境要求的接口是這些現存對象所不滿足的。
適配的意思是在不改變原有實現的基礎上,將原先不兼容的接口轉換為兼容的接口。在我們的生活中有著很多適配器的例子,筆記本的電源適配器、一些卡的USB讀卡器等等。
在Gof23這本書中將適配器模式分成了兩種:對象適配器和類適配器
對象適配器
上圖中的Target是客戶所期待的,希望去使用的類或接口。Adaptee是被適配的對象。Adapter為適配的對象。首先將上圖中的結構還原成代碼,如下:
/// <summary>/// 客戶要使用的類/// </summary>public abstract class Target{public abstract void Request();}/// <summary>/// 被適配的類/// </summary>public class Adaptee{public void SpecificRequest(){ }}/// <summary>/// 適配對象/// </summary>public class Adapter : Target{private Adaptee adapee = new Adaptee();public void Request(){adapee.SpecificRequest();}}/// <summary>/// 客戶程序/// </summary>public class App{static void Main(string[] args){Target target = new Adapter();//對客戶來說是調用的Request,實際上是調用的SpecificRequesttarget.Request();}}接著根據上面的思路來看一個實際例子,我們要來實現一個對棧的操作,有一個IStact接口,里面有三個方法Push(進棧)、Pop(出棧)和GetTopItem(取最頂層元素),這個IStact接口將相當于上面的Target,想要實現進棧出棧的操作,如果自己去實現數據結構顯得比較麻煩,在此可以將net提供的ArrayList類拿來一用,ArrayList類就是被適配的對象,相當于上面的Adaptee。在寫一個適配類StactAdapter類完成功能就可以了。
/// <summary> /// 棧的接口 /// </summary> public interface IStack {void Push(object item);void Pop();Object GetTopItem(); } /// <summary> /// 對象適配器 /// </summary> public class StactAdapter:IStack {ArrayList list;/// <summary>/// 構造函數中實例化ArrayList/// </summary>public StactAdapter(){list = new ArrayList();}/// <summary>/// 進棧/// </summary>/// <param name="item">壓入棧的元素</param>public void Push(object item){list.Add(item);}/// <summary>/// 出棧/// </summary>public void Pop(){list.RemoveAt(list.Count - 1);}/// <summary>/// 取最頂層的元素/// </summary>/// <returns></returns>public Object GetTopItem(){return list[list.Count - 1];} } /// <summary> /// 客戶調用 /// </summary> public class App {static void Main(string[] args){IStack myStack = new StactAdapter();myStack.Push("oec2003");myStack.Push("oec2004");myStack.Push("oec2005");myStack.Pop();Console.WriteLine(myStack.GetTopItem());} }Adapter模式理解起來也非常簡單,IStact中的Push和Pop方法就是添加元素和移除元素的功能,正好系統類ArrayList中就提供了Add和RemoveAt這樣的方法,所以就可以拿來借用,通過適配器類(StactAdapter)的轉換使得Push和Pop方法可以支持添加和移除元素的功能,就像我們經常使用的筆記本一樣,本來現實中的電壓和筆記本所需要的電壓不相符,通過電源適配器的轉換就將現實中的電壓轉換成筆記本所需要的電壓。
類適配器
類適配器中使用到了剁成繼承,從圖中可以看出Adapter繼承了Target和Adaptee,而在C#語言中不支持多繼承,如果一定要在C#中使用類適配器,那么Target和Adapter其中之一一定要為接口,這樣就有了一定的局限性。再者Adapter繼承了Target和Adapter后就擁有了這兩個的職責,這也違反了單一職責原則,所以通常我們使用對象適配器,下面還是給出配合上圖的代碼,Target設計成了接口。
/// <summary> /// 客戶要使用的類 /// </summary> public interface ITarget {public void Request(); } /// <summary> /// 被適配的類 /// </summary> public class Adaptee {public void SpecificRequest(){} } /// <summary> /// 適配對象 /// </summary> public class Adapter : Adaptee,ITarget {public void Request(){this.SpecificRequest();} } /// <summary> /// 客戶程序 /// </summary> public class App {static void Main(string[] args){ITarget target = new Adapter();//對客戶來說是調用的Request,實際上是調用的SpecificRequesttarget.Request();} }Adapter模式的幾個要點
Adapter模式主要英語于“希望復用一些現存的類,但是接口又與復用環境要求不一致的情況”,在遺留代碼復用、類庫遷移方面非常有用。
Gof23定義了兩種Adapter模式的實現結構:對象適配器和類適配器。但類適配器采用“多繼承”的實現方式,帶來了不良的高耦合,所以一般不推薦使用。對象適配器采用“對象組合”的方式,更符合松耦合。
Adapter模式可以實現的非常靈活,不必拘泥于Gof23中定義的兩種結構。例如,完全可以講Adapter模式中的“現存對象”作為新的接口方法參數,來達到適配的目的。
Adapter模式本身要求我們盡可能地使用“面向接口的編程”風格,這樣才能在后期方便適配。
?
?
作者:oec2003(水杯)出處:http://oec2003.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
轉載于:https://www.cnblogs.com/abenmao/archive/2012/05/25/2517989.html
總結
以上是生活随笔為你收集整理的设计模式笔记(7)---适配器模式(结构型)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像PSNR值及MSE值的计算
- 下一篇: 表达式与运算符