適配器模式(Adapter),將一個類的接口轉換成客戶但願的另一個接口。Adapter模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。javascript
在軟件開發中,系統的數據行爲都正確,但接口不符,咱們應該考慮用適配器,目的是使控制範圍以外的一個原有對象與某個接口匹配。適配器模式主要應用於但願複用一些現存的類,可是接口又與複用環境要求不一致的狀況。html
下面給出適配器模式的UML圖:java
下面來看下適配器模式的代碼結構圖:git
namespace ConsoleApplication1 { //Target類,客戶所指望的接口 class Target { public virtual void Request() { Console.WriteLine("普通請求!"); } } //Adaptee須要適配的類 class Adaptee { public void SpecificRequest() { Console.WriteLine("特殊的請求!"); } } //Adapter(經過在內部包裝一個Adapee對象,把源接口轉換成目標接口) class Adapter : Target { private Adaptee adaptee = new Adaptee(); //簡歷一個私有的Adaptee對象 public override void Request() { adaptee.SpecificRequest(); //這樣就能夠把表面上調用的Request()方法變成實際調用SpecificRequest() } } class Program { static void Main(string[] args) { Target target = new Target(); //客戶端只可以接受Target類 target.Request(); //並且要調用Target類的Request()方法,這樣只有經過Adapter白裝adaptee了。這就是所爲的適配器模式 Console.ReadKey(); } } }
使用一個已經存在的類,但若是它的接口,也就是它的方法和你所要求不相同時,就應該考慮適配器模式。可是適配器模式多少有點亡羊補牢的感受,所以應該在系統設計之初就規範好接口。設計模式
下面回到《大話設計模式》中的要命到NBA打球的例子:ide
namespace ConsoleApplication1 { abstract class Player { protected string name; public Player(string name) { this.name = name; } public abstract void Attack(); public abstract void Defense(); } //前鋒 class Forwards : Player { public Forwards(string name) : base(name) { } public override void Attack() { Console.WriteLine("前鋒{0}進攻",name); } public override void Defense() { Console.WriteLine("前鋒{0}防守",name); } } //中鋒 class Center : Player { public Center(string name) : base(name) { } public override void Attack() { Console.WriteLine("中鋒{0}進攻", name); } public override void Defense() { Console.WriteLine("中鋒{0}防守", name); } } //後衛 class Guards : Player { public Guards(string name) : base(name) { } public override void Attack() { Console.WriteLine("後衛{0}進攻", name); } public override void Defense() { Console.WriteLine("後衛{0}防守", name); } } //外籍中鋒 class ForeignCenter { private string name; public string Name { get { return name; } set { name = value; } } public void 進攻() //注意 外籍中鋒的語言不通,所以經過規範的抽象類Player的Attack()方法沒法調用 { Console.WriteLine("外籍中鋒{0}進攻", name); } public void 防守() { Console.WriteLine("外籍中鋒{0}防守", name); } } //翻譯者類 class Translator : Player { private ForeignCenter wjzf = new ForeignCenter(); public Translator(string name) : base(name) { wjzf.Name = name; } public override void Attack() //調用翻譯者的Attack()就至關於調用了 外籍中鋒的進攻,而翻譯者類是繼承自Player,所以兼容抽象 { wjzf.進攻(); } public override void Defense() { wjzf.防守(); } } class Program { static void Main(string[] args) { Player b = new Forwards("巴蒂爾"); b.Attack(); Player m = new Guards("麥迪"); m.Attack(); Player ym = new Translator("姚明"); //不能直接new外籍中鋒對象,由於調用外籍中鋒的進攻方法是進攻(),Player類對象沒法調用 ym.Attack(); ym.Defense(); Console.ReadKey(); } } }
輸出結果以下所示:post
適配器模式在.Net中的應用,DataAdapter用做DataSet和數據源之間的適配器以便檢索和保存數據。DataAdapter經過映射Fill(這更改了DataSet中的數據以便於數據源中的數據相匹配)和Update(這更改了數據源中的數據以便於DataSet中的數據相匹配)來提供這一適配器。學習