
一、生活中的扳手
假設我們在平時的工作中一直用12mm的扳手,如下圖所示:
突然有一天,我們要操作24mm的螺絲....
這時,我們會想到三種解決方案:
1,再重新采購一個24mm的扳手,以適應新的需求
2,讓對方的廠家螺絲變小,由24mm變為12mm以適應我們的扳手....這個解決方案看起來相當扯淡...
3,增加一個12mm與24mm的“扳手適配器”..把這個適配器“套在”我們已有的12mm扳手上,以使用這個適配器的另一端的24mm的接口。
基於我們可控制的條件來考慮,讓產商把所有的24mm螺絲改成12mm的螺絲是不可能的,所以我們只能在第一種和第二種方案中來選擇解決方案,然后我們再從成本上分析[在軟件中主要指人力成本,應對需求變化時所花費的成本],方案一固然也可以解決問題,但是一個新的扳手價格在45元左右,同樣,如果采用了方案3,一個“扳手適配器”也能解決我們的問題,但成本只有10元左右,從倍數的角度來看,我們解決同樣的問題,方案3相比方案1節省了3倍左右的金錢。
二、程序中的扳手
1,12mm扳手正常工作的情況下:
1 /// <summary> 2 /// 12mm的螺絲 3 /// </summary> 4 public class Screws_12mm 5 { 6 public string Turn() 7 { 8 return "12mm的螺絲在轉動..."; 9 } 10 } 11 /// <summary> 12 /// 12mm的扳手 13 /// </summary> 14 public class Wrench_12mm 15 { 16 Screws_12mm screwms; 17 18 public string Work() 19 { 20 screwms = new Screws_12mm(); 21 return screwms.Turn(); 22 } 23 } 24 /// <summary> 25 /// 使用 26 /// </summary> 27 class Program 28 { 29 static void Main(string[] args) 30 { 31 //使用12mm的扳手 32 Wrench_12mm wrench = new Wrench_12mm(); 33 Console.WriteLine(wrench.Work()); 34 Console.Read(); 35 } 36 }
類圖:
2,接口有變化,突然來了個24mm的螺絲,我們此時采用第三種解決方案,引入“扳手適配器”,
代碼:
1 /// <summary> 2 /// 24mm的螺絲 3 /// </summary> 4 public class Screws_24mm 5 { 6 public string Turn() 7 { 8 return "24mm的螺絲在轉動..."; 9 } 10 } 11 /// <summary> 12 /// 12mm的扳手 13 /// </summary> 14 public class Wrench_12mm 15 { 16 Screws_12mm screwms; 17 18 public virtual string Work() 19 { 20 screwms = new Screws_12mm(); 21 return screwms.Turn(); 22 } 23 } 24 /// <summary> 25 /// 適配器 26 /// </summary> 27 public class Adapter : Wrench_12mm 28 { 29 Screws_24mm screws; 30 public override string Work() 31 { 32 screws = new Screws_24mm(); 33 return screws.Turn(); 34 } 35 } 36 /// <summary> 37 /// 使用 38 /// </summary> 39 class Program 40 { 41 static void Main(string[] args) 42 { 43 //使用12mm的扳手和適配器 44 Wrench_12mm wrench = new Adapter(); 45 Console.WriteLine(wrench.Work()); 46 Console.Read(); 47 } 48 }
類圖:
三、適配器模式
適配器模式(英語:adapter pattern)有時候也稱包裝樣式或者包裝。將一個類的接口轉接成用戶所期待的。一個適配使得因接口不兼容而不能在一起工作的類工作在一起,做法是將類別自己的接口包裹在另一個類中。
在系統的“數據”與“行為”都正確,但是接口不同時,我們應該考慮使用適配器模式。
四、應用場景
“亡羊補牢”:像上面的例子一樣,本來我們一直對應的是12mm螺絲的工作,在設計之初並沒有想到我們會使用到24mm螺絲。此時,我們會使用適配器模式以補充不足。
在軟件維護的過程中,有時出現了新的接口,但是修改已往的代碼風險又很大,又不能要求接口改變,此時我們考慮應用"Adapter模式"。
“預先設計”:在設計之初,就有明顯的需求於預視到“要應對於不同的接口”,我們仍然以扳手為例,如下圖所示:
除非有明確的需求,否則不建議預先使用適配器模式,如上圖,我們買了個大包裝的“扳手套裝”,在其中我們能到幾個呢?到目前我們可能只用到了12mm與24mm這兩個,同時在設計之初,我們並不確定是否可以用到24mm的扳手,謹防“過渡設計”。