概念
提供了一個建立一系列相關或相關依賴對象的介面,而無需指定它們具體的類,也就是說我們經常學習到“一系列相關依賴的對象”的建立工作,但是由於需求的變化,往往存在著更多個物件的建立工作,為的是如何不用在使用常規的對象的建立方法(new),提供一種“封裝機制”來避免客戶程式和這樣“系列對象建立工作”的強耦合關係?降低用戶端和建立工作的強耦合度,我們引入了抽象原廠模式
目的
提供了一個建立一系列相關或相關依賴對象的介面,而無需指定它們具體的類
邏輯圖
結構圖
抽象原廠模式與Factory 方法模式的區別
抽象原廠模式是Factory 方法模式的升級版本,他用來建立一組相關或者相互依賴的對象。他與Factory 方法模式的區別就在於,Factory 方法模式針對的是一個產品等級結構;而抽象原廠模式則是針對的多個產品等級結構。在編程中,通常一個產品結構,表現為一個介面或者抽象類別,也就是說,Factory 方法模式提供的所有產品都是衍生自同一個介面或抽象類別,而抽象原廠模式所提供的產品則是衍生自不同的介面或抽象類別。
在抽象原廠模式中,有一個產品族的概念:所謂的產品族,是指位於不同產品等級結構中功能相關聯的產品組成的家族。抽象原廠模式所提供的一系列產品就組成一個產品族;而Factory 方法提供的一系列產品稱為一個等級結構。
具體代碼
//具體的工廠 class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } //抽象產品A abstract class AbstractProductA { } //抽象產品B abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } //具體實現A class ProductA1 : AbstractProductA { } //具體實現B1 class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } //具體實現A2 class ProductA2 : AbstractProductA { } //具體實現B2 class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } //用戶端 class Client { private AbstractProductA AbstractProductA; private AbstractProductB AbstractProductB; // Constructor public Client(AbstractFactory factory) { AbstractProductB = factory.CreateProductB(); AbstractProductA = factory.CreateProductA(); } public void Run() { AbstractProductB.Interact(AbstractProductA); } } 具體執行個體:
//定義的新類的介面 interface IDepartment { void Insert(Department department); Department GetDepartment(int id); } //繼承於IDepartment class SqlserverDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Sqlserver中給Department表增加一條記錄"); } public Department GetDepartment(int id) { Console.WriteLine("在Sqlserver中根據ID得到Department表一條記錄"); return null; } } //繼承於IDepartment class AccessDepartment : IDepartment { public void Insert(Department department) { Console.WriteLine("在Access中給Department表增加一條記錄"); } public Department GetDepartment(int id) { Console.WriteLine("在Access中根據ID得到Department表一條記錄"); return null; } }//抽象工廠介面 interface IFactory { IUser CreateUser(); IDepartment CreateDepartment(); } //AccessFactory類,實現Ifactory介面,執行個體化AccessUser和AccessDepartment class AccessFactory:IFactory { public IUser CreateUser() { return new AccessUser(); } public IDepartment CreateDepartment() { return new AccessDepartment(); } }//SqlserverFactory類,實現Ifactory介面,執行個體化Sqlserver和SqlserverDepartment class SqlServerFactory:IFactory { public IUser CreateUser() { return new SqlserverUser(); } public IDepartment CreateDepartment() { return new SqlserverDepartment(); } } 抽象原廠模式的優點
抽象原廠模式除了具有Factory 方法模式的優點外,最主要的優點就是可以在類的內部對產品族進行約束。所謂的產品族,一般或多或少的都存在一定的關聯,抽象原廠模式就可以在類內部對產品族的關聯關係進行定義和描述,而不必專門引入一個新的類來進行管理。
易於交換產品系列,由於具體工程類在一個應用中只需要初始化的時候出現一次,這就使用改變一個應用的具體工廠變得非常容易,它只需要改變具體工廠即可使用不同的產品配置
它讓具體的建立執行個體過程與用戶端分離,用戶端是通過它們的抽象介面操作執行個體,產品的具體類名也被具體工廠的實現分離,不會出現在用戶端中
抽象原廠模式的缺點
產品族的擴充將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。所以使用抽象原廠模式時,對產品等級結構的劃分是非常重要的。
適用情境
當需要建立的對象是一系列相互關聯或相互依賴的產品族時,便可以使用抽象原廠模式。說的更明白一點,就是一個繼承體系中,如果存在著多個等級結構(即存在著多個抽象類別),並且分屬各個等級結構中的實作類別之間存在著一定的關聯或者約束,就可以使用抽象原廠模式。假如各個等級結構中的實作類別之間不存在關聯或約束,則使用多個獨立的工廠來對產品進行建立,則更合適一點。
總結
無論是簡單原廠模式,Factory 方法模式,還是抽象原廠模式,他們都屬於原廠模式,在形式和特點上也是極為相似的,他們的最終目的都是為瞭解耦。在使用時,我們不必去在意這個模式到底Factory 方法模式還是抽象原廠模式,因為他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的Factory 方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由於類中的產品構成了不同等級結構中的產品族,它就變成抽象原廠模式了;而對於抽象原廠模式,當減少一個方法使的提供的產品不再構成產品族之後,它就演變成了Factory 方法模式。