1.概述
在軟體開發中,我們經常會遇到系統間整合,在系統整合時,最常見的問題就是系統間的介面不一致。很多能夠滿足功能的系統模組,由於介面不一致,導致無法使用。例如,常用的媒體播放器是MS Media player和RealPlayer,他們的檔案結構和軟體介面完全不同,前者支援WMF格式的音頻和視頻,後者支援RM格式的音頻和視頻。如果我們希望自己的軟體能夠播放這兩種播放器播放相應格式的音頻和視頻,我們該怎麼辦呢?一切從頭開始,重寫一個支援這兩種格式的播放軟體?呵呵,你要不覺得累你就重寫了,呵呵。
適配器模式(Adapter):將一個的介面轉化成客戶希望的另外一個介面.Adapter模式使得原本由於介面不相容而不能一起工作的的那些類可以一起工作。 適配器模式的意圖就是使介面不相容的類能夠一起工作,通常情況下,這些介面不相容的類在邏輯上的功能是一致或相似的。在開發中,系統的資料和行為都正確,但介面不符時,我們就應該考慮用適配器模式,目的就在於使控制範圍之外的一個原有對象與某個介面匹配。適配器模式主要用於希望服用一些現有的類,但是介面又與環境要求不一致的情況。
適配器有類適配器和對象適配器兩種類型,二者的意圖相同,只是實現的方法和適用的情況不同。類適配器採用繼承來實現,對象適配器則採用組合的方法來實現。
類適配器:類適配器通過多重繼承對一個介面與另一個介面進行匹配,其結構如所示:
Target定義了Client使用的與特定領域相關的介面,Client通過調用Target實現某一特定的操作。Adaptee是一個已經存在的類,需要與Target協同工作,這個介面需要適配。Adapter適配器適配Adaptee和Target介面。在類適配器中,通過繼承獲得Adaptee中的方法:
/// <summary>
/// Adaptee
/// </summary>
public class Adaptee
{
public void Execute()
{
}
}
/// <summary>
/// Target
/// </summary>
public class Target
{
public void Do()
{
}
}
/// <summary>
/// Adapter,.NET中不支援多繼承
/// </summary>
public class Adapter : Adaptee, Target
{
#region Target 成員
public void Do()
{
this.Execute();
}
#endregion
}
複製代碼
在.NET中類適配器使用受到一定的限制,由於.NET不支援多繼承,即一個類只能有一個父類。因此當Target是一個類,而不是一個介面時就無法實作類別適配器,這時需要使用對象適配器。
對象適配器:對象適配器採用對象組合,通過引用一個類與另一個類介面,其結構所示:
在對象適配器中,通過組合獲得Adaptee對象:
/// <summary>
/// Adaptee
/// </summary>
public class Adaptee
{
public void Execute()
{
}
}
/// <summary>
/// Target
/// </summary>
public class Target
{
public void Do()
{
}
}
/// <summary>
/// Adapter,.NET中不支援多繼承
/// </summary>
public class Adapter : Target
{
private Adaptee adaptee;
public Adapter(Adaptee ap)
{
adaptee = ap;
}
#region Target 成員
public void Do()
{
adaptee.Execute();
}
#endregion
}
複製代碼
使用場合:需要使用一個已經存在的類,但介面與設計要求不符;希望建立一個可以複用的類,該類可以與其他不相關的類或者是將來不可預見的類協同工作。在雙方多不太容易修改的時候再使用適配器模式適配。
2.執行個體
大話設計模式中的籃球翻譯適配器,先來看結構圖:
代碼如下:
//籃球運動員
public abstract class Player
{
protected string name;
public Player(string name)
{
this.name = name;
}
public abstract void Attack();
public abstract void Defense();
}
//前鋒
public 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);
}
}
//中鋒
public 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);
}
}
//後衛
public 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);
}
}
//外籍中鋒
public class ForeignCenter
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public void 進攻()
{
Console.WriteLine("外籍中鋒 {0} 進攻", name);
}
public void 防守()
{
Console.WriteLine("外籍中鋒 {0} 防守", name);
}
}
//翻譯者
public class Translator : Player
{
private ForeignCenter wjzf = new ForeignCenter();
public Translator(string name)
: base(name)
{
wjzf.Name = name;
}
public override void Attack()
{
wjzf.進攻();
}
public override void Defense()
{
wjzf.防守();
}
}
複製代碼
調用代碼: static void Main(string[] args)
{
Player b = new Forwards("巴蒂爾");
b.Attack();
Player m = new Guards("麥克格雷迪");
m.Attack();
//Player ym = new Center("姚明");
Player ym = new Translator("姚明");
ym.Attack();
ym.Defense();
Console.Read();
}
複製代碼
結果顯示:
前鋒 巴蒂爾 進攻
後衛 麥克格雷迪 進攻
外籍中鋒 姚明 進攻
外籍中鋒 姚明 防守
有了翻譯者(適配器),姚明不懂英文,火箭的教練和球員也不用學中文就可以使火箭整個團隊溝通合作的很好。哈哈。
3.總結
1).NET中的適配器模式DataAdapter。DataAdapter用作DataSet和資料來源之間的適配器以便檢索和儲存資料。DataAdapter通過映射Fill(更改了DataSet中的資料以便與資料來源中的資料相匹配)和Update(更改了資料來源中的資料以便與DataSet中的資料相匹配),來提供這一適配器。
實現要點
Adapter模式主要應用於“希望複用一些現存的類,但是介面又與複用環境要求不一致的情況”,在遺留代碼複用、類庫遷移等方面非常有用;Adapter模式有對象適配器和類適配器兩種形式的實現結構,但是類適配器採用“多繼承”的實現方式,帶來了不良的高耦合,所以一般不推薦使用。對象適配器採用“對象組合”的方式,更符合松耦合精神;Adapter模式的實現可以非常的靈活,不必拘泥於GOF23中定義的兩種結構。例如,完全可以將Adapter模式中的“現存對象”作為新的介面方法參數,來達到適配的目的;Adapter模式本身要求我們儘可能地使用“面向介面的編程”風格,這樣才能在後期很方便的適配。
效果:
對於類適配器:用一個具體的Adapter類對Adaptee和Taget進行匹配。結果是當我們想要匹配一個類以及所有它的子類時,類Adapter將不能勝任工作;使得Adapter可以重定義Adaptee的部分行為,因為Adapter是Adaptee的一個子類;僅僅引入了一個對象,並不需要額外的指標一間接得到Adaptee.
對於對象適配器:允許一個Adapter與多個Adaptee,即Adaptee本身以及它的所有子類(如果有子類的話)同時工作。Adapter也可以一次給所有的Adaptee添加功能。使得重定義Adaptee的行為比較困難。這就需要產生Adaptee的子類並且使得Adapter引用這個子類而不是引用Adaptee本身。
適用性
在以下各種情況下使用適配器模式:系統需要使用現有的類,而此類的介面不符合系統的需要;想要建立一個可以重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。這些源類不一定有很複雜的介面;(對對象適配器而言)在設計裡,需要改變多個已有子類的介面,如果使用類的適配器模式,就要針對每一個子類做一個適配器,而這不太實際。
在對兩個無關類進行適配的時候考慮一下適配的代價,一個非常龐大的適配器可能會對系統效能有影響。
參考資料:http://terrylee.cnblogs.com/archive/2006/02/18/333000.html
轉載自:http://www.cnblogs.com/peida/archive/2008/07/15/1235214.html