適配器模式簡介:
將一個類別的介面轉換成客戶希望的另外一個介面。 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> /// 类 .NET適配器模式講解(Adapter Pattern) /// </summary> class Program { static void Main(string[] args) { ILogTarget dbLog = new DatabaseLogAdapter(); dbLog.Write("程序启动成功"); dbLog = new FileLogAdapter(); dbLog.Write("程序启动成功"); } }
.的方式實現了新的日誌功能的遷移變化,下面我們使用物件適配器,可以區別發現兩種方式的特別之處。原來寫日誌的方法依舊不變: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類,裡面繼承了FileLogbaseLog, ILogFileLogAdapter 類,DatabaseLogAdapter類,裡面繼承了FileLogbaseLog, ILogFileTargetTarget,重寫的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> /// 对象.NET適配器模式講解(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("程序启动成功"); } }
比較兩者的遷移變化,在我們得到的適配器,Adbase具有它所繼承的父類別的所有的行為,同時也具有介面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> /// 对象.NET適配器模式講解(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); } }
結果肯定是不能的,一個類別不能有多個基類,這樣寫明細有錯誤。所有針對不同的情況,我們都應該採用適當的方式去進行適配調度。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持PHP中文網。