1. 概述
抽象工廠模式為一個產品家族提供了統一的創建接口。當需要這個產品家族的某一系列的時候,可以從抽象工廠中選出相對應的系列來創建一個具體的工廠類別。
2. 抽象工廠模式中的角色
2.1 抽象工廠(AbstractFactory):擔任這個角色的是工廠方法模式的核心,它是與應用系統商業邏輯無關的。
2.2 具體工廠(ConcreteFactory):這個角色直接在客戶端的調用下創建產品的實例。這個角色含有選擇合適的產品對象的邏輯,而這個邏輯是與應用系統的商業邏輯緊密相關的。
2.3 抽象產品(AbstractProduct):擔任這個角色的類是工廠方法模式所創建的對象的父類,或它們共同擁有的接口。
2.4 具體產品(ConcreteProduct):抽象工廠模式所創建的任何產品對象都是某一個具體產品類的實例。這是客戶端最終需要的東西,其內部一定充滿了應用系統的商業邏輯。
3. 實例:更換數據庫。現有系統使用的是SqlServer數據庫,它的Licence是付費的,有的客戶想使用免費的數據庫服務,如Access。有的客戶擁有其它數據庫服務商的Licence,他們也不想使用還要另付費的SqlServer。
3.1 解決這個問題的根本是將應用程序與數據庫解耦,使得應用程序不再依賴某一個具體的數據庫。抽象工廠給我們提供了解決方案。
3.2 實現類圖
3.3 實現代碼
3.3.1 抽象工廠類,提供了創建一組相關或相互依賴的對象的接口。
/// <summary> /// 抽象工廠類 /// </summary> public interface IDatabaseFactory { IEmployee CreateEmployee(); IUser CreateUser(); }
3.3.2 具體工廠類,提供了創建SqlServer,或Access具體產品的實現
/// <summary> /// 與SqlServer相關產品的實現 /// </summary> public class SqlServerDatabaseFactory : IDatabaseFactory { public IEmployee CreateEmployee() { return new SqlEmployee(); } public IUser CreateUser() { return new SqlUser(); } } /// <summary> /// 與Access相關產品的實現 /// </summary> public class AccessDatabaseFactory : IDatabaseFactory { public IEmployee CreateEmployee() { return new AccessEmployee(); } public IUser CreateUser() { return new AccessUser(); } }
3.3.3 兩個抽象產品,分別是IUser和IEmployee
/// <summary> /// 抽象產品 /// </summary> public interface IUser { User GetUser(); bool SaveUser(); } /// <summary> /// 抽象產品 /// </summary> public interface IEmployee { Employee GetEmployee(); bool SaveEmployee(); }
3.3.4 具體產品的實現
/// <summary> /// 與SqlServer相關的具體產品User /// </summary> public class SqlUser : IUser { public User GetUser() { return null; } public bool SaveUser() { return false; } } /// <summary> /// 與SqlServer相關的具體產品Employee /// </summary> public class SqlEmployee : IEmployee { public SqlEmployee() { } public Employee GetEmployee() { return null; } public bool SaveEmployee() { return false; } } /// <summary> /// 與Access相關的具體產品User /// </summary> public class AccessUser : IUser { public AccessUser() { } public User GetUser() { return null; } public bool SaveUser() { return false; } } /// <summary> /// 與Access相關的具體產品Employee /// </summary> public class AccessEmployee : IEmployee { public AccessEmployee() { } public Employee GetEmployee() { return null; } public bool SaveEmployee() { return false; } }
4. 模式總結
4.1 優點
4.1.1 具體產品從客戶代碼中被分離出來
4.1.2 容易改變產品的系列(如SqlServer產品系列,Access產品系列)
4.1.3 將一個系列的產品族統一到一起創建
4.2 缺點
在產品族中擴展新的產品是很困難的,它需要修改抽象工廠的接口,如增加一種產品Customer變得非常困難。
4.3 實用范圍
4.3.1 一個系統要獨立於它的產品的創建、組合和表示時。
4.3.2 一個系統要由多個產品系列中的一個來配置時。
4.3.3 當你要強調一系列相關的產品對象的設計以便進行聯合使用時。
4.3.4 當你提供一個產品類庫,而只想顯示它們的接口而不是實現時。