簡單工廠,Factory 方法和抽象工廠是一個大家族,三個很好的姐妹。那麼我們分別來介紹一下這三個姐妹。
一、簡單工廠 定義
簡單原廠模式是由一個工廠對象決定建立出哪一種產品類的執行個體。簡單原廠模式是原廠模式家族中最簡單實用的模式,可以理解為是不同原廠模式的一個特殊實現。
結構圖
模式實現
public class OperationFactory { public static Operation createOperate(string operate) { Operation oper = null; switch (operate) { case "+": oper = new OperationAdd(); break; case"-": oper = new OperationSub(); break; case "*": oper=new OperationMul(); break; case"/": oper=new OperationDiv(); break; } return oper; }
用戶端代碼:
Operation oper; oper = OperationFactory.createOperate("+"); oper.NumberA = 1; oper.NumberB = 2; double result = oper.GetResult();
這樣子如果要增加複雜的運算,不僅要增加子類,還要修改運算類工廠,由於開放——封閉原則是對擴充是開放的,對修改是關閉的,就違背了開放——擴充原則。於是簡單工廠就被淘汰了。因為簡單工廠很容易違反高內聚責任分配原則,因此只在一般很簡單的情況下應用。
於是大姐抽象工廠和二姐Factory 方法都全力以赴,參加比賽.
二、抽象工廠 定義
提供一個建立一系列相關或相互依賴對象的介面,而無需指定他們具體的類.
結構圖
抽象工廠的優缺點
優點
第一,易於交換產品系列,由於具體工廠類,在一個應用中只需要在初始化的時候出現一次,這就是的改變一個應用的具體工廠變得非常容易,他只需要改變具體工廠即可使用不同的產品配置.
第二,它讓具體的建立執行個體過程與用戶端分離,用戶端是通過他們的抽象介面操縱執行個體,產品的具體類名也被具體工廠的實現分離,不會出現在客戶代碼中.
缺點
由於增加功能進而添加多個子類會使得抽象工廠很臃腫,而且在每個類的開始都需要聲明,執行個體化.這樣更改很浪費.
用簡單工廠改造抽象工廠結構圖
實現
class DataAccess { private static readonly string db = "Sqlserver"; //private static readonly string db="Access"; 資料庫名稱可替換成Access public static IUser CreateUser() { IUser result = null; switch (db) { case "Sqlserver": result = new SqlserverUser(); break; case "Access": result = new AccessUser(); break; } return result; } public static IDepartment CreateDepartment() { IDepartment result = null; switch (db) //由於db事先設定,此處可以根據選擇執行個體化出相應對象 { case "Sqlserver": result = new SqlserverDepartment(); break; case"Access": result = new AccessDepartment(); break; } return result; } }
用戶端代碼
static void Main(string[] args) { User user = new User(); Department dept = new Department(); IUser iu = DataAccess.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = DataAccess.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); }
用戶端沒有出現任何一個SQL Server或者Access的字樣,達到瞭解耦的目的。
DataAccess類取代三個工廠類,由於實現設定了db的值(Sqlserver或Access),所以,簡單工廠的方法都不需要輸入參數,這樣在用戶端就只需要DataAccess.CreateUser()和DataAccess.CreateDepartment()來產生具體的資料可訪問類執行個體。
用反射+設定檔實現資料訪問程式
所有用在簡單工廠的地方,都可以考慮用反射技術來去除switch或if,解除分支判斷帶來的耦合。反射技術可以很好的解決它們難以應對的變化,難以維護和擴充的詬病。
操作
添加一個App.config檔案,內容如下:
<?xml version="1.0" encoding="utf-8" ?><configuration> <appSettings> <add key="DB" value="Sqlserver"/> //設定檔,sqlserver可以替換成Access </appSettings></configuration>
添加引用System.configruation,並在程式開頭增加using System.AppSettings;然後更改DataAccess類的欄位DB的賦值代碼。
Private static readonly string db=ConfigurationManager.AppSettings["DB"];
總結
抽象原廠模式:多個抽象產品類,每個抽象產品類可以派生出多個具體產品類;一個抽象工廠類,可以派生出多個具體工廠類;每個具體工廠類可以建立多個具體產品類的執行個體。
三、Factory 方法模式
Factory 方法模式可以用一個很簡單的執行個體來理解就是雷鋒依然在人間。
定義
Factory 方法模式是定義一個用於建立對象的介面,讓子類決定執行個體化哪一個類。Factory 方法使一個類的執行個體化延遲到其子類。
結構圖
具體實現
例如結構圖如下的實現
可以用工廠類去實現運算類,相應的子類工廠去實現子運算類。需要哪個就用哪個工廠類去執行個體化相應的運算類就可以了。
(1)先構建一個介面
interface IFactory { Operation CreateOperation(); }
(2)用具體工廠去實現這個介面
class AddFactory:IFactory { public Operation CreateOperation() { return new OperationAdd(); } } class SubFactory:IFactory { public Operation CreateOperation() { return new OperationSub(); } } class DivFactory:IFactory { public Operation CreateOperation() { return new OperationDiv(); } class MulFactory:IFactory { public Operation CreateOperation() { return new OperationMul(); } }
用戶端的實現
IFactory operFactory = new AddFactory(); Operation oper = operFactory.CreateOperation(); oper.NumberA = 1 ; oper.NumberB = 2; double result = oper.GetResult();
總結
Factory 方法模式是一個抽象產品類,可以派生出多個具體產品類;一個抽象工廠類,可以派生出多個具體工廠類;每個具體工廠類只能建立一個具體產品類的執行個體。
四、對比
簡單工廠VS.抽象方法
簡單原廠模式:工廠角色可以和具體產品角色合并。
抽象原廠模式中,每一個具體工廠類可以有一個靜態方法,其傳回值類型是該具體工廠類自己。
簡單工廠VS.Factory 方法
簡單原廠模式的最大優點在於工廠類中包含了必要的邏輯判斷,根據用戶端的選擇條件動態執行個體化相關的類,對於用戶端來說,去除了與具體產品的依賴。Factory 方法模式實現時,用戶端需要決定執行個體化哪一個工廠來實現運算類,選擇判斷的問題還是存在的,也就是說,Factory 方法把簡單的內部邏輯判斷一道了用戶端代碼來進行。你想要加功能,本來是改工廠類的,而現在是修改用戶端。
Factory 方法模式VS.抽象原廠模式
Factory 方法是基礎可以根據需要靈活運用,向抽象工廠演化。
Factory 方法模式只有一個抽象的產品類,而抽象原廠模式又多個;Factory 方法模式的具體工廠類只能建立一個具體產品類的執行個體,而抽象原廠模式可以建立多個。
五、總結
三個原廠模式都屬於設計模式中的建立型模式。主要功能都是協助我們把對象的執行個體化部分抽取了出來,最佳化了系統的架構,增強了系統的擴充性。
簡單原廠模式的工廠類一般是使用靜態方法,通過接收的參數的不同來返回不同的對象執行個體。如果不修改代碼的話,是無法擴充的。
Factory 方法是針對每一種產品提供一個工廠類。通過不同的工廠執行個體來建立不同的產品執行個體。在同一等級結構中,支援增加任意產品。
抽象工廠是應對產品族概念的。比如說,每個汽車公司可能要同時生產汽車,轎車,客車,每一個工廠都由建立這些不同種類車的方法。