簡單工廠模式(嚴格來講這不算一種Gof的設計模式,更像是一種編程習慣)屬於類的建立型模式,又叫作靜態工廠方法模式。經過專門定義一個類來負責建立其餘類的實例,被建立的實例一般都具備相同的父類,應用繼承將決定工廠的生產什麼產品的決定權直接交到了客戶手中,而後客戶在輸入本身的需求,獲得最終的結果。git
運用簡單工廠模式實現生產pizza的業務場景。github
/// <summary> /// pizza建立工廠 /// </summary> public class PizzaFactory { public static Pizza CreatePizza(string pizzaType) { switch (pizzaType) { case "Cheese": return new CheesePizza(); case "ApplePie": return new ApplePiePizza(); default: return new SomeOtherPizza(); } } } public abstract class Pizza { public string Name { get; set; } public void Prepare() { Console.WriteLine($"Preparing {Name}"); } public void Cut() { Console.WriteLine($"Cutting the {Name}"); } public void Bake() { Console.WriteLine($"Baking the {Name}"); } public void Box() { Console.WriteLine($"Boxing the {Name}"); } } public class ApplePiePizza : Pizza { public ApplePiePizza() { Name = "ApplePie"; } } public class CheesePizza : Pizza { public CheesePizza() { Name = "Cheese"; } } public class SomeOtherPizza : Pizza { public SomeOtherPizza() { Name = "Other"; } } //調用 class Program { static void Main(string[] args) { Pizza pizza = PizzaFactory.CreatePizza("cheese"); pizza.Box(); } } //輸出: //Preparing Cheese //Cutting the Cheese //Baking the Cheese //Boxing the Cheese
簡單工廠模式實現了生成Pizza類的代碼跟客戶端代碼分離,在工廠類中你能夠添加所需的生成Pizza的邏輯代碼,可是,簡單工廠並不符合「開放-封閉」原則(對擴展開放,對修改關閉),若是要加一種類型VeggiePizza,你就要修改工廠類裏面的生成產品的代碼,在這裏你就要增長Swich-Case。對於這個問題,咱們的工廠方法模式就能夠解決這個問題。編程
運用工廠模式實現生產pizza的業務場景。設計模式
/// <summary> /// 工廠接口 /// </summary> interface IFactory { Pizza CreatePizza(); } /// <summary> /// CheesePizza工廠方法 /// </summary> public class CheesePizzaFactory : IFactory { public Pizza CreatePizza() { return new CheesePizza(); } } /// <summary> /// ApplePiePizza工廠方法 /// </summary> public class ApplePiePizzaFactory : IFactory { public Pizza CreatePizza() { return new ApplePiePizza(); } } class Program { static void Main(string[] args) { IFactory factory = new CheesePizzaFactory(); Pizza cheesePizza = factory.CreatePizza(); cheesePizza.Prepare(); cheesePizza.Cut(); cheesePizza.Bake(); cheesePizza.Box(); //輸出: //Preparing Cheese //Cutting the Cheese //Baking the Cheese //Boxing the Cheese } }
工廠模式中咱們經過對應的工廠類來生成對應的Pizza,在這裏符合「開閉」原則,不管加多少Pizza類,咱們都不用修改原來類中的代碼,而是經過增長工廠類來實現。可是這仍是有缺點的,若是產品Pizza類過多,咱們就要生成不少的工廠類。假如咱們要實現的產品接口不止一個,也就是有多個產品接口,不一樣產品接口有對應的產品族。什麼是產品族呢?簡單的理解就是,不一樣類型的Pizza會在不一樣的地區會有不一樣的準備方式,以材料(麪糰Dough,果醬Sauce)的不一樣而變幻口味等,同地區不一樣類型的Pizza能夠組成一個產品族。對於這種狀況咱們能夠採用抽象工廠模式。ide
運用工廠模式實現生產pizza的業務場景。this
/// <summary> /// 麪糰 /// </summary> public interface Dough { void Dough(); } /// <summary> /// 紐約麪糰 /// </summary> public class NYDough : Dough { public void Dough() { Console.WriteLine("NYDough"); } } /// <summary> /// 芝加哥麪糰 /// </summary> public class ChicagoDough : Dough { public void Dough() { Console.WriteLine("ChicagoDough"); } } /// <summary> /// 果醬 /// </summary> public interface Sauce { void Sauce(); } /// <summary> /// 紐約果醬 /// </summary> public class NYSauce : Sauce { public void Sauce() { Console.WriteLine("NYSauce"); } } /// <summary> /// 芝加哥果醬 /// </summary> public class ChicagoSauce : Sauce { public void Sauce() { Console.WriteLine("ChicagoSauce"); } } /// <summary> /// 建造披薩原料工廠 接口 /// </summary> public interface IPizzaIngredientFactory { Dough CreateDough(); Sauce CreateSauce(); } /// <summary> /// 紐約披薩工廠 /// </summary> public class NYPizzaIngredientFactory : IPizzaIngredientFactory { public Dough CreateDough() { return new NYDough(); } public Sauce CreateSauce() { return new NYSauce(); } } /// <summary> /// 芝加哥披薩工廠 /// </summary> public class ChicagoPizzaIngredientFactory : IPizzaIngredientFactory { public Dough CreateDough() { return new ChicagoDough(); } public Sauce CreateSauce() { return new ChicagoSauce(); } } public abstract class Pizza { public string Name { get; set; } /// <summary> /// 麪糰 /// </summary> public Dough Dough { get; set; } /// <summary> /// 醬汁 /// </summary> public Sauce Sauce { get; set; } public abstract void Prepare(); public void Cut() { Console.WriteLine($"Cutting the {Name}"); } public void Bake() { Console.WriteLine($"Baking the {Name}"); } public void Box() { Console.WriteLine($"Boxing the {Name}"); } } public class ApplePiePizza : Pizza { IPizzaIngredientFactory _pizzaIngredientFactory; public ApplePiePizza(IPizzaIngredientFactory pizzaIngredient) { this._pizzaIngredientFactory = pizzaIngredient; Name = "ApplePie"; } public override void Prepare() { Console.WriteLine($"Preparing { Name}"); Dough = _pizzaIngredientFactory.CreateDough(); Dough.Dough(); Sauce = _pizzaIngredientFactory.CreateSauce(); Sauce.Sauce(); } } public class CheesePizza : Pizza { IPizzaIngredientFactory _pizzaIngredientFactory; public CheesePizza(IPizzaIngredientFactory pizzaIngredient) { this._pizzaIngredientFactory = pizzaIngredient; Name = "Cheese"; } public override void Prepare() { Console.WriteLine($"Preparing { Name}"); Dough = _pizzaIngredientFactory.CreateDough(); Dough.Dough(); Sauce = _pizzaIngredientFactory.CreateSauce(); Sauce.Sauce(); } } public class SomeOtherPizza : Pizza { public SomeOtherPizza() { Name = "Other"; } public override void Prepare() { throw new NotImplementedException(); } } // <summary> /// 工廠接口 /// </summary> interface IFactory { Pizza CreatePizza(IPizzaIngredientFactory pizzaIngredientFactory); } /// <summary> /// CheesePizza工廠方法 /// </summary> public class CheesePizzaFactory : IFactory { public Pizza CreatePizza(IPizzaIngredientFactory pizzaIngredientFactory) { return new CheesePizza(pizzaIngredientFactory); } } /// <summary> /// ApplePiePizza工廠方法 /// </summary> public class ApplePiePizzaFactory : IFactory { public Pizza CreatePizza(IPizzaIngredientFactory pizzaIngredientFactory) { return new ApplePiePizza(pizzaIngredientFactory); } } //調用 class Program { static void Main(string[] args) { IPizzaIngredientFactory pizzaIngredientFactory = new NYPizzaIngredientFactory(); IFactory factory = new CheesePizzaFactory(); Pizza cheesePizza = factory.CreatePizza(pizzaIngredientFactory); cheesePizza.Prepare(); cheesePizza.Cut(); cheesePizza.Bake(); cheesePizza.Box(); //輸出: //Preparing Cheese //NYDough //NYSauce //Cutting the Cheese //Baking the Cheese //Boxing the Cheese } }
調用者無須知道所建立的具體產品類的類名,只須要知道具體產品類所對應的的參數便可。設計
系統擴展困難,一旦添加新產品就不得不修改工廠邏輯,在產品類型較多時,有可能會形成工廠邏輯過於複雜,不利於系統的擴展和維護。code
在系統中加入新產品時,無需修改抽象工廠和抽象產品提供的接口,也無須修改客戶端,還無須修改其餘的具體工廠和具體產品,而只要加入一個具體工廠和具體產品就能夠了。所以,系統的可擴展性獲得了保證,符合開閉原則。對象
因爲考慮到系統的可擴展性,須要引入抽象層,且在實現時可能須要用到反射等技術,增長了系統的實現難度。繼承
增長新的產品族很方便,無需修改已有系統,符合開閉原則。
增長新的產品等級結構由於須要對原有系統進行較大的修改,甚至須要修改抽象層代碼,這必然會帶來較大的不便,在這個角度,它違背了開閉(對擴展開放,對修改封閉)原則。