1. 適配器模式簡介
1.1 模式定義
適配器模式:通過一個類的接口轉換成客戶希望的另外一個接口,使原本由於接口不兼容而不能一起工作的那些類可以一起工作。
適配器從結構上分為:類適配器和對象適配器。其中類適配器使用繼承關系來對類進行適配,對象適配器使用對象引用來進行適配。
C#實現類適配器時,Target只能是接口。實現對象適配器時,Target可以是抽象類也可以是接口。
1.2 使用頻率
中高
2. 類適配器模式結構
2.1 結構圖
2.1.1 類適配器結構圖
2.1.2 對象適配器結構圖
2.2 參與者
適配器模式參與者:
◊ Target:Client所使用的目標接口,可以是接口或抽象類。由於C#不支持多類繼承,故把Target定義為接口。
◊ Adaptee:需要適配的類接口。
◊ Adapter:適配器,負責Adaptee的接口與Target接口進行適配。
◊ Client:與符合Target接口的對象協調的類。
在適配器模式中,類Adapter實現適配器的功能,它在Client與Adaptee之間加入Adapter,這樣Client把請求發給接口為Target的類Adapter,再由Adapter調用Adaptee,從而實現Client調用Adaptee。
3. 適配器模式結構實現
3.1 類適配器結構實現
ITarget.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter { public interface ITarget { void Request(); } }
Adaptee.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter { public class Adaptee { public void SpecificRequest() { Console.WriteLine("Called SpecificRequest()"); } } }
Adapter.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter { public class Adapter : Adaptee, ITarget { public void Request() { this.SpecificRequest(); } } }
Client.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter { public class Client { static void Main(string[] args) { ITarget t = new Adapter(); t.Request(); } } }
運行輸出:
Called SpecificRequest()
請按任意鍵繼續. . .
3.2 對象適配器結構實現
Client需要調用Request方法,而Adaptee並沒有該方法,為了使Client能夠使用Adaptee類,需要提供一個類Adapter。這個類包含了一個Adaptee的實例,將Client與Adaptee銜接起來。
ITarget.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter { public interface ITarget { void Request(); } }
Target.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter { public class Target : ITarget { public virtual void Request() { Console.WriteLine("Called Target Request()"); } } }
Adaptee.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter { public class Adaptee { public void SpecificRequest() { Console.WriteLine("Called SpecificRequest()"); } } }
Adapter.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter { public class Adapter : Target { private Adaptee _adaptee = new Adaptee(); public override void Request() { _adaptee.SpecificRequest(); } } }
Client.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter { public class Client { static void Main(string[] args) { ITarget t = new Adapter(); t.Request(); } } }
4. 適配器模式實踐應用
以手機充電的電源適配器為例,用適配器模式的解決方案。
4.1 類適配器結構實現
ITarget.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter { public interface ITarget { void GetPower(); } }
Power.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter { public class Power { public void GetPower220V() { Console.WriteLine("從電源中得到220V的電壓"); } } }
Adapter.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter { public class Adapter : Power, ITarget { public void GetPower() { this.GetPower220V(); Console.WriteLine("得到手機的充電電壓!"); } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter { public class Client { static void Main(string[] args) { Console.WriteLine("手機:"); ITarget t = new Adapter(); t.GetPower(); } } }
運行輸出:
手機:
從電源中得到220V的電壓
得到手機的充電電壓!
請按任意鍵繼續. . .
4.2>、對象適配器結構實現
ITarget.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter { public interface ITarget { void GetPower(); } }
Power.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter { public class Power { public void GetPower220V() { Console.WriteLine("從電源中得到220V的電壓"); } } }
Adapter.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter { public class Adapter : ITarget { public Power _power; public Adapter(Power power) { this._power = power; } /// <summary> /// 得到想要的電壓 /// </summary> public void GetPower() { _power.GetPower220V(); Console.WriteLine("得到手機的充電電壓!"); } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter { public class Client { static void Main(string[] args) { Console.WriteLine("手機:"); ITarget t = new Adapter(new Power()); t.GetPower(); } } }
5、適配器模式應用分析
適配器模式適用情形:
◊ 當適用一個已存在的類,而它的接口不符合所要求的情況;
◊ 想要創建一個可以復用的類,該類可以與原接口的類協調工作;
◊ 在對象適配中,當要匹配數個子類的時候,對象適配器可以適配它們的父類接口。
適配器模式特點:
類適配器
◊ 使得Adapter可以重定義Adaptee的部分行為。因為Adapter是Adaptee的一個子類;
◊ 僅僅引入了一個對象,並不需要額外的指針間接得到Adaptee。
對象適配器
◊ 允許一個Adapter與多個Adaptee同時工作。Adapter也可以一次給所有的Adaptee添加功能;
◊ 使得重定義Adaptee的行為比較困難。需要生成一個Adaptee的子類,然后使Adapter引入這個子類而不是引用Adaptee本身。