退款業務強耦合到售後系統中,並且業務代碼分散到各個業務層,嚴重缺乏系統的領域邊界和分層設計,重構後退款業務邏輯不強依賴售後核心業務邏輯,做到可以獨立部署。 ...
總體介紹:
工廠模式主要有三種類型:簡單工廠、工廠方法和抽象工廠,該模式用於封裝和管理對象的創建,是一種創建型模式。
萬物皆對象,創建對象時必然需要new該對象,當需要更改對象時,需要把項目中所有地方都修改一遍,這顯然違背了軟體設計的開閉原則。
如果使用工廠來生成對象,那麼我們只需要跟工廠打交道就可以了。如果要更新對象時,直接在工廠里更換即可。這就實現了對象解耦。
所以工廠模式主要用來解耦代碼,將對象的創建和使用分離,使得代碼更加靈活和可維護。
定義創建對象的介面,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
適用於創建對象需要大量重覆的步驟,或者需要依賴於其它對象的情況,它提供了一種方式來封裝多個相關或依賴對象的創建邏輯。
(一)簡單工廠基礎介紹:
這是工廠模式的最基本形式,通過定義一個工廠類,它可以根據參數的不同返回不同類的實例,被創建的實例通常都具有共同的父類。
因為在簡單工廠模式中用於創建實例的方法是靜態(static)方法,因此簡單工廠模式又被稱為靜態工廠方法模式,它屬於類創建型模式,但不屬於GOF23種設計模式。
簡單工廠包含三大角色:
- 抽象產品(抽象類):定義了產品的規範,描述了產品的主要特征和功能。它是工廠類創建的所有對象的父類,封裝了各種產品對象的共有方法。
- 具體產品(子類):繼承抽象產品的子類,某個產品的具體實現類。
- 具體工廠(實例化對象類):它是簡單工廠模式的核心,負責實現創建所有產品實例的內部邏輯;其可以被外界直接調用,創建所需的產品對象。
- 特性和功能:定義一個用於創建對象的介面,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
- 使用環境:當一個類不知道它所必須創建的對象的類的時候。
- 註意事項:每增加一個產品就需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度。
- 優點:一個調用者想創建一個對象,只要知道其名稱就可以了。
- 缺點:增加新的產品需要修改工廠介面,違背了“開放-封閉原則”。
簡單工廠創建方式:
- 首先定義一個抽象產品類。
1 /// <summary> 2 /// 該類是產品的父類即抽象產品,定義所有子類的共有屬性和方法 3 /// </summary> 4 public abstract class Coffee 5 { 6 /// <summary> 7 /// 方便演示,只定義兩個代表性方法。 8 /// </summary> 9 public abstract void GetName(); 10 11 public void AddSugar() 12 { 13 Console.WriteLine("加糖"); 14 } 15 }
該類主要定義了產品的共有屬性和方法,用於子類繼承和實現。
- 其次定義每個產品的具體實現子類。
1 public class AmericanCoffee : Coffee 2 { 3 public override void GetName() 4 { 5 Console.WriteLine("我是一杯美式咖啡。"); 6 } 7 } 8 9 public class LatterCoffe: Coffee 10 { 11 public override void GetName() 12 { 13 Console.WriteLine("我是一杯拿鐵咖啡。"); 14 } 15 }
該類實現並繼承自抽象類,如需增加產品可直接創建新的子類並繼承自抽象類即可。
- 然後定義核心類,即工廠類。
1 public class CoffeeFactory 2 { 3 public CoffeeFactory() 4 { 5 } 6 7 /// <summary> 8 /// 簡單工廠中必須要有一個方法來根據指定的邏輯創建實例 9 /// </summary> 10 /// <param name="fruitType"></param> 11 /// <returns></returns> 12 public static Coffee OrderCoffe(CoffeeEnum coffeeEnum) 13 { 14 switch (coffeeEnum) 15 { 16 case CoffeeEnum.AmericanCoffee: 17 return new AmericanCoffee(); 18 case CoffeeEnum.LatterCoffe: 19 return new LatterCoffe(); 20 } 21 return null; 22 } 23 24 public enum CoffeeEnum 25 { 26 AmericanCoffee, 27 LatterCoffe 28 } 29 }
該類通過創建了一個枚舉類型參數來選擇需要創建的產品實例。
- 最後客戶端調用。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //通過CoffeeFactory產品工廠創建了AmericanCoffee產品實例 6 Coffee coffee = CoffeeFactory.OrderCoffe(CoffeeFactory.CoffeeEnum.AmericanCoffee); 7 coffee.GetName(); 8 9 //通過CoffeeFactory產品工廠創建了LatterCoffe產品實例 10 coffee = CoffeeFactory.OrderCoffe(CoffeeFactory.CoffeeEnum.LatterCoffe); 11 coffee.GetName(); 12 coffee.AddSugar(); 13 } 14 }
根據客戶端的選擇條件來動態的實例化相關的類,
對於客戶端來說,其去除了與具體產品之間的依賴。
簡單工廠模式的缺點主要就是違背了開-閉原則,在上面的 Demo 中,如果我要再增加一種產品。
那麼,首先是定義一個新產品子類,讓其繼承自抽象類,然後呢,您還必須修改工廠類。
所以進而改進形成了工廠方法模式。
(二)工廠方法基礎介紹:
這是一種更高級的工廠模式,它通過抽象介面或基類中的工廠方法來創建對象。
具體實現由子類負責,因此更加靈活。這種設計方式有利於實現開閉原則,即對擴展開放,對修改封閉。
簡單工廠把全部的事情,在一個地方(類)全部處理完,而工廠方法卻不同,
定義一個用於創建對象的介面,讓子類決定實例化哪個產品類對象。工廠方法使一個產品類的實例化延遲到其工廠的子類。
這樣一來,擴展產品種類就不必修改工廠函數了,核心類就變成抽象類,工廠方法模式將生成具體產品的任務分發給具體的產品工廠。
也就是相當於工廠總部不生產產品了,交給下轄分工廠進行生產。
要增加產品類時也要相應地增加工廠類,不需要修改工廠類的代碼了,這樣就解決了簡單工廠模式的缺點。
工廠方法模式是簡單工廠模式的進一步抽象。由於使用了多態性,工廠方法模式保持了簡單工廠模式的優點,而且剋服了它的缺點。
工廠方法模式的主要角色:
抽象工廠:在抽象工廠類中聲明瞭工廠方法,用於返回一個產品。提供了創建產品的介面,調用者通過它訪問具體工廠的工廠方法來創建產品。
具體產品工廠:它是抽象工廠類的子類,實現了在抽象工廠中聲明的工廠方法,完成具體產品的創建。並可由客戶端調用,返回一個具體產品類的實例。
抽象產品:它是定義產品的介面,定義了產品的規範,描述了產品的主要特性和功能,是工廠方法模式所創建對象的公共父類。
具體產品:它實現了抽象產品介面,某種類型的具體產品由專門的具體工廠創建,具體工廠和具體產品之間一一對應。
缺點:每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,這增加了系統的複雜度。
工廠方法創建方式:
- 抽象產品類:
1 /// <summary> 2 /// 該類是產品的父類即抽象產品,定義所有子類的共有屬性和方法 3 /// </summary> 4 public abstract class Coffee 5 { 6 /// <summary> 7 /// 方便演示,只定義兩個代表性方法。 8 /// </summary> 9 public abstract void GetName(); 10 11 public void AddSugar() 12 { 13 Console.WriteLine("加糖"); 14 } 15 }
- 具體產品類:
1 public class AmericanCoffee : Coffee 2 { 3 public override void GetName() 4 { 5 Console.WriteLine("我是一杯美式咖啡。"); 6 } 7 } 8 9 public class LatterCoffe: Coffee 10 { 11 public override void GetName() 12 { 13 Console.WriteLine("我是一杯拿鐵咖啡。"); 14 } 15 }
- 抽象工廠:
1 /// <summary> 2 /// 抽象工廠 3 /// </summary> 4 public abstract class CoffeeFactory 5 { 6 public abstract Coffee GetCoffee(); 7 }
- 具體產品工廠:
1 /// <summary> 2 /// 美式咖啡工廠 3 /// </summary> 4 public class AmericanFactory:CoffeeFactory 5 { 6 public override Coffee GetCoffee() 7 { 8 return new AmericanCoffee(); 9 } 10 } 11 12 /// <summary> 13 /// 拿鐵咖啡工廠 14 /// </summary> 15 public class LatterFactory : CoffeeFactory 16 { 17 public override Coffee GetCoffee() 18 { 19 return new LatterCoffe(); 20 } 21 }
- 客戶端調用:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //首先創建一個美式咖啡工廠,只負責生產美式咖啡產品 6 CoffeeFactory coffeeFactory = new AmericanFactory(); 7 //在美式咖啡工廠中生產一個美式咖啡產品 8 Coffee coffee = coffeeFactory.GetCoffee(); 9 coffee.GetName(); 10 11 //創建一個拿鐵咖啡工廠,只負責生產拿鐵咖啡產品 12 coffeeFactory = new LatterFactory(); 13 //在工廠中生產一個拿鐵咖啡產品 14 coffee = coffeeFactory.GetCoffee(); 15 coffee.GetName(); 16 //咖啡中加糖 17 coffee.AddSugar(); 18 } 19 }
通過客戶端調用方式可以看出,不同產品的生產由原來的總工廠變為了各個分工廠去負責。
用戶只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體創建過程。
在系統增加新的產品時只需要添加具體產品類和對應的具體工廠類,無須對原工廠進行任何修改,滿足開閉原則。
(三)抽象工廠基礎介紹:
上面兩種模式不管工廠怎麼拆分抽象,都只是針對一類產品,直接生成實例,這些工廠只生產同種類產品。
但是抽象工廠模式不同,抽象工廠模式並不直接生成實例, 而是用於對產品類簇的創建。
通俗點來講就是:簡單工廠和工廠方法模式的工作是生產產品,那麼抽象工廠模式的工作就是生產工廠的。
是一種為訪問類提供一個創建一組相關或相互依賴對象的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。
抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產一個等級的產品,而抽象工廠模式可生產多個等級的產品。
抽象工廠的最大好處在於交換產品系列非常方便,只需要改變具體工廠即可使用不同的產品配置。
抽象工廠模式的主要角色:
抽象工廠:在抽象工廠類中聲明瞭多個工廠方法,用於返回多個產品。提供了創建產品的介面,它包含多個創建產品的方法,可以創建多個不同等級的產品。
具體產品工廠:它是抽象工廠類的子類,實現了在抽象工廠中聲明的多個工廠方法,完成多個具體產品的創建。
抽象產品:它是定義一個產品的介面,定義了一個產品的規範,描述了一個產品的主要特性和功能。抽象工廠模式有多個抽象產品。
具體產品:實現了抽象產品角色所定義的介面,由具體工廠來創建,它同具體工廠之間是多對一的關係。
總的來說工廠方法模式一個工廠只生產一個產品,抽象工廠模式一個工廠生產多個產品,形成一個產品套餐,而多個工廠組成套餐系列。
抽象工廠創建方式:
- 抽象產品類,有多少個不同產品就創建多少個抽象產品類。
1 /// <summary> 2 /// 咖啡產品抽象類 3 /// </summary> 4 public abstract class Coffee 5 { 6 /// <summary> 7 /// 方便演示,只定義兩個代表性方法。 8 /// </summary> 9 public abstract void GetName(); 10 11 public void AddSugar() 12 { 13 Console.WriteLine("加糖"); 14 } 15 } 16 17 /// <summary> 18 /// 甜點產品抽象類 19 /// </summary> 20 public abstract class Dessert 21 { 22 public abstract void GetName(); 23 }
實例中創建了兩種產品,即咖啡和甜品。
- 具體產品類,不同產品繼承不同抽象類。
1 public class AmericanCoffee : Coffee 2 { 3 public override void GetName() 4 { 5 Console.WriteLine("我是一杯美式咖啡。"); 6 } 7 } 8 9 public class LatterCoffe: Coffee 10 { 11 public override void GetName() 12 { 13 Console.WriteLine("我是一杯拿鐵咖啡。"); 14 } 15 } 16 17 public class MatchaMousse: Dessert 18 { 19 public override void GetName() 20 { 21 Console.WriteLine("我是一塊抹茶慕斯。"); 22 } 23 } 24 25 public class Tiramisu: Dessert 26 { 27 public override void GetName() 28 { 29 Console.WriteLine("我是一塊提拉米蘇。"); 30 } 31 }
實例中定義了兩種咖啡和兩種甜點,咖啡為一個產品等級,甜點是另外一個產品等級。
- 抽象工廠類,有多少個系列就可以創建多少個抽象工廠類。本實例只創建了一個風味系列的工廠。
1 /// <summary> 2 /// 風味工廠 3 /// </summary> 4 public abstract class RelishFactory 5 { 6 //生產一杯咖啡 7 public abstract Coffee GetCoffee(); 8 //生產一塊甜點 9 public abstract Dessert GetDessert(); 10 }
實例中定義了一個系列的工廠,如果新增一個不同產品等級的奶茶,那就可以在風味工廠中生產一杯奶茶。同一種口味綁定為一個系列即一個抽象工廠。
- 具體工廠類,同一系列可以創建多個具體的工廠,負責同一系列下的不同產品出的創建。本實例創建了風味系列下的不同風味工廠的創建。
1 /// <summary> 2 /// 美式風味工廠 3 /// </summary> 4 public class AmericanRelishFactory : RelishFactory 5 { 6 public override Coffee GetCoffee() 7 { 8 return new AmericanCoffee(); 9 } 10 11 public override Dessert GetDessert() 12 { 13 return new MatchaMousse(); 14 } 15 } 16 17 /// <summary> 18 /// 義大利風味工廠 19 /// </summary> 20 public class ItalyRelishFactory : RelishFactory 21 { 22 public override Coffee GetCoffee() 23 { 24 return new LatterCoffe(); 25 } 26 27 public override Dessert GetDessert() 28 { 29 return new Tiramisu(); 30 } 31 }
實例中創建了兩種不同口味的工廠,選擇對應口味的工廠,可以生產出對應口味的不同產品。
比如選擇了美式口味工廠,該工廠可以生產出美式咖啡和抹茶慕斯。
實際上是該工廠將這兩個不同等級的產品進行綁定,形成了一個產品族。
- 客戶端調用:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //首先創建一種口味工廠 6 RelishFactory relishFactory = new AmericanRelishFactory(); 7 //然後對應口味工廠中生產出對應口味的不同產品。 8 Coffee coffee = relishFactory.GetCoffee(); 9 coffee.GetName(); 10 Dessert dessert = relishFactory.GetDessert(); 11 dessert.GetName(); 12 13 Console.WriteLine("換一種口味"); 14 relishFactory = new ItalyRelishFactory(); 15 coffee = relishFactory.GetCoffee(); 16 coffee.GetName(); 17 dessert = relishFactory.GetDessert(); 18 dessert.GetName(); 19 } 20 }
實例中可以看出創建了一個美式口味工廠,
該工廠就可以生產出符合該口味的不同產品。
其本質就是將相同口味的不同產品綁定成一個產品族,形成一個產品族工廠。
如果有多個產品族,那就創建多個產品族工廠就可以了。優點:當一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象。缺點:當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。
總結:
簡單工廠把全部的事情,在一個地方(類)全部處理完,
而工廠方法卻不同,
其是通過創建一個框架,
然後讓子類決定要如何實現。
而抽象工廠則是定義一個負責創建一組產品(也就是一個產品族)的介面,
抽象工廠的最大好