適配器模式簡介:
將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。
在電腦編程中,適配器模式(有時候也稱封裝樣式或者封裝)將一個類的介面適配成使用者所期待的。一個適配允許通常因為介面不相容而不能在一起工作的類工作在一起,做法是將類自己的介面包裹在一個已存在的類中。
適配器模式結構圖:
引入執行個體進行說明:
以日誌記錄程式為Demo說明,在任何一套軟體中都會有對應的日誌管理模組,假如如果我們在開發軟體中的日記記錄採用第三方的日誌組件進行日誌記錄,它採用的是Log.Write("寫日誌");的方式我們的程式在開發中,大量執行個體化日記記錄對象,採用的Log.Write()方式進行日誌記錄,但是現在第三方的日誌組件現在不免費了,需要收費了,於是我們打算使用一種新的日誌管理模組,只不過它提供給我們的API介面是採用Log.WriteLog("新的寫日誌的方式");進行日誌記錄。這個時候問題就出現了,如何應對這種遷移的變化
類適配器模式
1.原來日誌的介面,採用的是Write(“寫日誌”);方法
/// <summary>/// 原來的日誌記錄介面/// </summary>public interface ILogTarget{ /// <summary> /// 原來的寫日誌方法 /// </summary> void Write(string info);}
2.然而現在的寫日誌的介面,採用的是WriteLog("寫日誌");裡面實現了寫日誌的新的方式:將日誌寫到檔案中,資料庫中
/// <summary>/// 抽象寫日誌類/// </summary>public abstract class LogAdaptee{ /// <summary> /// 寫日誌 /// </summary> public abstract void WriteLog(string info);}
/// <summary>/// 寫檔案日誌記錄/// </summary>public class FileLog:LogAdaptee{ /// <summary> /// 寫日誌到檔案中 /// </summary> public override void WriteLog(string info) { Console.WriteLine("記錄到文字檔:"+info); }}
/// <summary>/// 往資料庫中寫日誌/// </summary>public class DatabaseLog:LogAdaptee{ /// <summary> /// 重寫寫日誌方法 /// </summary> public override void WriteLog(string info) { Console.WriteLine("記錄到資料庫:"+info); }}
3.如何使用者兩個新對象中的方式,替換原來的寫日誌的方式?
/// <summary>/// 採用新的寫日誌的方式,寫入到資料庫中/// </summary>public class DatabaseLogAdapter:DatabaseLog,ILogTarget{ /// <summary> /// 在重寫ILogTarget介面中的的Write方法裡面調用新的寫日誌的方式WriteLog /// </summary> public void Write(string info) { WriteLog(info); }}
/// <summary>/// 採用新的寫日誌的方式,寫入到文字檔/// </summary>public class FileLogAdapter : FileLog, ILogTarget{ /// <summary> /// 在重寫ILogTarget介面中的的Write方法裡面調用新的寫日誌的方式WriteLog /// </summary> public void Write(string info) { this.WriteLog(info); }}
4.調用依據使用的原來寫日誌的方法,但是確實使用的新的寫日誌的方式:
/// <summary>/// 類 適配器模式(Adapter Pattern)/// </summary>class Program{ static void Main(string[] args) { ILogTarget dbLog = new DatabaseLogAdapter(); dbLog.Write("程式啟動成功"); dbLog = new FileLogAdapter(); dbLog.Write("程式啟動成功"); }}
對象適配器模式
1.方式採用的是類適配器的方式實現了新的日誌功能的遷移變化,下面我們使用對象適配器,可以區別發現兩種方式的特別之處。原來寫日誌的方法依舊不變:Write("寫日誌");
/// <summary>/// 原來的日誌記錄介面/// </summary>public interface ILogTarget{ /// <summary> /// 原來的寫日誌方法 /// </summary> void Write(string info);}
2.現在的寫日誌的介面,採用的是WriteLog("寫日誌");裡面實現了寫日誌的新的方式:將日誌寫到檔案中,資料庫中:
/// <summary>/// 抽象寫日誌類/// </summary>public abstract class LogAdaptee{ /// <summary> /// 寫日誌 /// </summary> public abstract void WriteLog(string info);}
/// <summary>/// 寫檔案日誌記錄/// </summary>public class FileLog:LogAdaptee{ /// <summary> /// 寫日誌到檔案中 /// </summary> public override void WriteLog(string info) { Console.WriteLine("記錄到文字檔:"+info); }}
/// <summary>/// 往資料庫中寫日誌/// </summary>public class DatabaseLog:LogAdaptee{ /// <summary> /// 重寫寫日誌方法 /// </summary> public override void WriteLog(string info) { Console.WriteLine("記錄到資料庫:"+info); }}
3.上面我們添加了FileLogAdapter 類,DatabaseLogAdapter類,繼承了FileLog,DatabaseLog, ILogTarget介面,重寫Write方法裡面調用新的寫日誌的方式WriteLog,使用這樣的方式進行了遷移變化。下面使用對象適配:
/// <summary>/// 對象適配,繼承ILogTarget,裡面有LogAdaptee抽象日誌類對象。/// </summary>public class LogAdapter:ILogTarget{ /// <summary> /// 抽象寫日誌類 /// </summary> private LogAdaptee _adaptee; public LogAdapter(LogAdaptee adaptee) { this._adaptee = adaptee; } public void Write(string info) { _adaptee.WriteLog(info); }}
4.在程式中的調用:
/// <summary>/// 對象適配器模式(Adapter Pattern)/// </summary>class Program{ static void Main(string[] args) { ILogTarget dbLog = new LogAdapter(new DatabaseLog()); dbLog.Write("程式啟動成功"); ILogTarget fileLog = new LogAdapter(new FileLog()); fileLog.Write("程式啟動成功"); }}
比較兩者的遷移變化,在類適配方式中,我們得到的適配器類DatabaseLogAdapter和FileLogAdapter具有它所繼承的父類的所有的行為,同時也具有介面ILogTarget的所有行為,這樣其實是違背了物件導向設計原則中的類的單一職責原則,而對象適配器則更符合物件導向的精神,所以在實際應用中不太推薦類適配這種方式。假設我們要適配出來的類在記錄日誌時同時寫入檔案和資料庫,那麼用對象適配器我們會這樣去寫:
/// <summary>/// 對象適配,繼承ILogTarget,裡面有LogAdaptee抽象日誌類對象。/// </summary>public class LogAdapter:ILogTarget{ /// <summary> /// 抽象寫日誌類 /// </summary> private LogAdaptee _adapteed; /// <summary> /// 抽象寫日誌類 /// </summary> private LogAdaptee _adapteef; public LogAdapter(LogAdaptee adapteed, LogAdaptee adapteef) { this._adapteed = adapteed; this._adapteef = adapteef; } public void Write(string info) { _adapteed.WriteLog(info); _adapteef.WriteLog(info); }}
調用:
/// <summary>/// 對象適配器模式(Adapter Pattern)/// </summary>class Program{ static void Main(string[] args) { //同時寫日誌到檔案和資料庫 ILogTarget dbLog = new LogAdapter(new FileLog(), new DatabaseLog()); dbLog.Write("程式啟動成功"); }}
如果改用類適配器:我們難道使用這樣的寫法達到目的?
public class DatabaseLogAdapter : DatabaseLog, FileLog, ILogTarget{ public void Write(string info) { this.WriteLog(info); }}
結果肯定是不能的,一個類不能具有多個基類,這樣寫明細有錯誤。所有針對不同的情況,我們應該採用合適的方式去進行適配調度。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援topic.alibabacloud.com。