今天我們來講一下適配器模式。下麵,我們描述一個場景: 不管是籃球隊還是足球隊,都會有外援的,在隊內訓練與安排戰術的時候,外援可能聽不懂漢語的,那麼,他們怎麼交流呢,這就需要一個翻譯了。其實,這個翻譯就起到了一個適配器的效果。 何為適配器模式:將一個介面轉換成為客戶希望的另外一個介面,使得原本由於介面 ...
今天我們來講一下適配器模式。下麵,我們描述一個場景:
不管是籃球隊還是足球隊,都會有外援的,在隊內訓練與安排戰術的時候,外援可能聽不懂漢語的,那麼,他們怎麼交流呢,這就需要一個翻譯了。其實,這個翻譯就起到了一個適配器的效果。
何為適配器模式:將一個介面轉換成為客戶希望的另外一個介面,使得原本由於介面不相容而不能在一起的類可以在一起工作。
系統的數據和運行都正確,但是介面不匹配是,我們可以考慮用適配器模式來解決。
好,下麵我們來看一下適配器模式的簡單的代碼結構:
1 /// <summary> 2 /// 客戶所期待的介面 3 /// </summary> 4 class Target 5 { 6 public virtual void Request() 7 { 8 Console.WriteLine("普通請求!"); 9 } 10 } 11 /// <summary> 12 /// 需要適配的類 13 /// </summary> 14 class Adaptee 15 { 16 public void SpecificRequest() 17 { 18 Console.WriteLine("特殊請求!"); 19 } 20 } 21 /// <summary> 22 /// 通過在內部包裝一個Adaptee對象,把源介面轉換成目標介面 23 /// </summary> 24 class Adapter : Target 25 { 26 private Adaptee adaptee = new Adaptee();//建立一個私有的Adaptee對象 27 public override void Request() 28 { 29 adaptee.SpecificRequest();//這樣就可以把錶面上調用Request()方法變成實際調用SpecificRequest() 30 } 31 }
客戶端調用:
1 public static void Main() 2 { 3 Target target = new Adapter(); 4 target.Request();//對於客戶端來說,調用的就是Target的Request() 5 Console.ReadKey(); 6 }
什麼時候使用適配器模式呢?
1、想使用一個已經存在的類,但是它的方法和你要求的方法不同時,應該考慮使用適配器模式。
2、兩個類做的事情相似,但是具有不同的介面時,可以考慮使用適配器模式。
使用適配器模式,可以讓客戶端統一的調用同一個介面就行了。這樣可以使代碼更直接,更簡潔,更緊湊。
好的,下麵我們用代碼來描述一下NBA的場景
1 /// <summary> 2 /// 抽象出來的球員類 3 /// </summary> 4 abstract class Player 5 { 6 protected string name; 7 8 public Player(string name) 9 { 10 this.name = name; 11 } 12 13 public abstract void Attack();//進攻的方法 14 public abstract void Defense();//防守的方法 15 } 16 /// <summary> 17 /// 前鋒 18 /// </summary> 19 class Forwards:Player 20 { 21 public Forwards(string name) : base(name) 22 { 23 } 24 25 public override void Attack() 26 { 27 Console.WriteLine($"前鋒{name}進攻"); 28 } 29 30 public override void Defense() 31 { 32 Console.WriteLine($"前鋒{name}防守"); 33 } 34 } 35 /// <summary> 36 /// 中鋒 37 /// </summary> 38 class Center:Player 39 { 40 public Center(string name) : base(name) 41 { 42 } 43 44 public override void Attack() 45 { 46 Console.WriteLine($"中鋒{name}進攻"); 47 } 48 49 public override void Defense() 50 { 51 Console.WriteLine($"中鋒{name}防守"); 52 } 53 } 54 /// <summary> 55 /// 後衛 56 /// </summary> 57 class Guards:Player 58 { 59 public Guards(string name) : base(name) 60 { 61 } 62 63 public override void Attack() 64 { 65 Console.WriteLine($"後衛{name}進攻"); 66 } 67 68 public override void Defense() 69 { 70 Console.WriteLine($"後衛{name}防守"); 71 } 72 }
客戶端調用:
1 public static void Main() 2 { 3 Player b = new Forwards("巴蒂爾"); 4 b.Attack(); 5 Player m = new Guards("麥克格雷迪"); 6 m.Attack(); 7 Player ym = new Center("姚明"); 8 ym.Attack();//姚明問:Attack()是什麼意思? 9 ym.Defense();//姚明問:Defense()是什麼意思? 10 Console.ReadKey(); 11 }
這裡就有一個問題了,如果姚明剛來NBA是,他對英語不是很精通,所以聽不懂英文,所以,他需要一個翻譯。換句話說,姚明是外籍中鋒,他需要一個翻譯者(適配器)來適配他。
我們有一個外籍中鋒類
1 class ForeignCenter 2 { 3 private string name; 4 5 public string Name 6 { 7 get 8 { 9 return name; 10 } 11 12 set 13 { 14 name = value; 15 } 16 } 17 18 public void 進攻()//表明‘外籍中鋒’只懂中文‘進攻’ 19 { 20 Console.WriteLine($"外籍中鋒{name}進攻"); 21 } 22 23 public void 防守()//表明‘外籍中鋒’只懂中文‘防守’ 24 { 25 Console.WriteLine($"外籍中鋒{name}防守"); 26 } 27 }
還有一個翻譯者類,將英文翻譯成他能聽懂的中文"進攻,防守"
1 class Translator:Player 2 { 3 private ForeignCenter wjzf = new ForeignCenter();//聲明並實例化一個內部‘外籍中鋒’對象,表明翻譯者與外籍中鋒有關聯 4 public Translator(string name) : base(name) 5 { 6 wjzf.Name = name; 7 } 8 9 public override void Attack()//翻譯者將'Attack'翻譯為‘進攻’告訴外籍中鋒 10 { 11 wjzf.進攻(); 12 } 13 14 public override void Defense()//翻譯者將'Attack'翻譯為‘防守’告訴外籍中鋒 15 { 16 wjzf.防守(); 17 } 18 }
客戶端:
1 public static void Main() 2 { 3 Player b = new Forwards("巴蒂爾"); 4 b.Attack(); 5 Player m = new Guards("麥克格雷迪"); 6 m.Attack(); 7 Player ym = new Translator("姚明"); 8 ym.Attack();//姚明問:Attack()是什麼意思? 9 ym.Defense();//姚明問:Defense()是什麼意思? 10 Console.ReadKey(); 11 }
這樣,我們就將NBA案例用適配器模式完成了。
其實,在.net中的一些類庫,他們也用到了適配器模式,我們經常用到的DataAdapter就是用到了適配器模式的應用。
好了,今天先講到這裡了,下一篇,我們講 備忘錄模式
本系列將持續更新,喜歡的小伙伴可以點一下關註和推薦,謝謝大家的支持