設計模式之工廠模式
定義:
定義一個建立物件的介面,但讓這個介面的實現類來決定例項化哪個類。工廠方法讓類的例項化推遲到子類中進行。也就是說,工廠方法模式會定義一個單獨的方法去建立或者管理物件。
考慮到建立物件的功能粒度,比較好的方式是未每一個具體目標物件設定一個單獨的工廠實現類以及物件建立方法。
工廠方法模式的類圖:
只去看定義,可能學術化太強,不足以形成一種比較形象的思維。讓我們來做一個這樣的思考:
首先,介面更多的是強調行為,我們是賦予這個介面建立物件的職責。這個時候,大家暫時不用去考慮具體實現的事情,把關注點放在建立物件這一抽象概念上,具體開發上就是關注當前的介面。
同時,我們採用面向物件的設計原則,儘量做到介面設計的職責單一。如果在具體的設計上涉及多個場景,可以考慮抽象工廠,這個會在以後的篇幅裡回顧。
綜上所述,工廠方法模式,有著很多優勢:
- 最大的優勢莫過於,它體現著面向物件的開閉原則:
我們為什麼要對每個物件都設計一個工廠介面,就是因為我們不希望因為未來不缺性的需求而影響現有功能,所以我們需要開放出一個口子,既能保持現有設計,又能不斷的擴充套件新功能,也是就是動態擴充套件。
- 其次,採用較細的粒度設計,也穩定了當前的設計,減少了未來的影響,這是單一職責的好處。
當然,工廠模式也有著很明顯的缺陷:
- 首先類的個數成倍數級增加
- 同時引入的抽象層或者說是抽象概念,也在一定程度上增加了系統理解的難度,根據實現方式的需要也有可能會增加系統額外的開發,因為有些功能的實現方式還會考慮反射等
應用場景:
- 當一個類不需要依賴其他類而只需要依賴其介面的時候,可以考慮工廠模式
- 為了使系統更好的適應未來不缺性的需要,可以考慮功能擴充套件,這一點可以看看.NET Core關於Configuration功能的原始碼
Demo:
最後我們看看demo吧,這是一個非常簡單的demo,正常來說,工廠模式涵蓋的內容很多,思維不要太過侷限於demo,更多還應該考慮每個工廠可能還有自己特殊的地方,畢竟已經設計了單獨的工廠類了。
以下demo的場景是想找到一個廚師去做飯,廚師角色暫時按照男女廚師來區分。
1 public interface IFactory 2 { 3ICook GetCooker(); 4 }
1 public class ManFactory : IFactory 2 { 3public ICook GetCooker() 4{ 5return new IManCook(); 6} 7 }
1 public class WomanFactory : IFactory 2 { 3public ICook GetCooker() 4{ 5return new IWomanCook(); 6} 7 }
1 public interface ICook 2 { 3void DoMeal(); 4 }
1 public class IManCook : ICook 2 { 3public void DoMeal() 4{ 5Console.WriteLine("男廚師做飯"); 6} 7 }
1 public class IWomanCook : ICook 2 { 3public void DoMeal() 4{ 5Console.WriteLine("女廚師做飯"); 6} 7 }
1 public class Program 2 { 3static void Main(string[] args) 4{ 5//找男廚師做飯 6IFactory manFactory = new ManFactory(); 7ICook manCook = manFactory.GetCooker(); 8manCook.DoMeal(); 9 10//找女廚師做飯 11IFactory womanFactory = new ManFactory(); 12ICook womanCook = womanFactory.GetCooker(); 13womanCook.DoMeal(); 14} 15 }