工廠方法模式
動機創建一個對象往往需要復雜的過程,所以不適合包含在一個複合工廠中,當有新的產品時,需要修改這個複合的工廠,不利於擴展。
而且,有些對象的創建可以需要用到復合工廠訪問不到的信息,所以,定義一個工廠接口,通過實現這個接口來決定實例化那個產品,這就是工廠方法模式,讓類的實例化推遲到子類中進行。
目的
1. 定義一個接口,讓子類決定實例化哪個產品。
2. 通過通用接口創建對象。
實現
1. 產品接口和具體產品很好理解。
2. 工廠類提供一個工廠方法,返回一個產品對象。但是這個工廠方法是抽象的。
3. 具體工廠類實現工廠方法,完成具體產品的創建。
//幾個Button類class Button{/* ...*/} class WinButton extends Button{/* ...*/} class MacButton extends Button{/* ...*/} //它們的工廠類interface ButtonFactory{ abstract Button createButton(); } class WinButtonFactory implements ButtonFactory{ Button createButton(){ return new WinButton(); } } class MacButtonFactory implements ButtonFactory{ Button createButton(){ return new MacButton(); } }適用場景
1. 創建對象時有比較多重複的代碼時,可以考慮使用工廠方法模式執行這些重複的部分。
2. 創建對象需要訪問某些信息,而這些信息不應該包含在工廠類,那麼可以讓子類來實現對象的創建。
3. 需要集中管理對象的創建,保持程序的一致性時。
抽象工廠模式
定義抽象工廠模式提供了一種方式,可以將一組具有同一主題的單獨的工廠封裝起來。在正常使用中,客戶端程序需要創建抽象工廠的具體實現,然後使用抽象工廠作為接口來創建這一主題的具體對象。客戶端程序不需要知道(或關心)它從這些內部的工廠方法中獲得對象的具體類型,因為客戶端程序僅使用這些對象的通用接口。抽象工廠模式將一組對象的實現細節與他們的一般使用分離開來。
“工廠”是創建產品(對象)的地方,其目的是將產品的創建與產品的使用分離。抽象工廠模式的目的,是將若干抽象產品的接口與不同主題產品的具體實現分離開。這樣就能在增加新的具體工廠的時候,不用修改引用抽象工廠的客戶端代碼。
使用抽象工廠模式,能夠在具體工廠變化的時候,不用修改使用工廠的客戶端代碼,甚至是在運行時。然而,使用這種模式或者相似的設計模式,可能給編寫代碼帶來不必要的複雜性和額外的工作。正確使用設計模式能夠抵消這樣的“額外工作”。
實現
1. AbstractFactory - 定義創建抽象產品的接口方法。
2. ConcreteFactory - 實現方法創建具體的產品。
3. AbstractProduct - 聲明不同類型的產品的接口。
4. Product - 定義ConcreteFactory對應的具體產品,實現AbstractProduct接口。
5. Client - 使用AbstractFactory和AbstractProduct類。
abstract class AbstractProductA{ public abstract void operationA1(); public abstract void operationA2(); } class ProductA1 extends AbstractProductA{ ProductA1(String arg){ System.out.println("Hello "+arg); } // Implement the code here public void operationA1() { }; public void operationA2() { }; } class ProductA2 extends AbstractProductA{ ProductA2(String arg){ System.out.println("Hello "+arg); } // Implement the code here public void operationA1() { }; public void operationA2() { }; } abstract class AbstractProductB{ //public abstract void operationB1(); //public abstract void operationB2(); } class ProductB1 extends AbstractProductB{ ProductB1(String arg){ System.out.println("Hello "+arg); } // Implement the code here } class ProductB2 extends AbstractProductB{ ProductB2(String arg){ System.out.println("Hello "+arg); } // Implement the code here } abstract class AbstractFactory{ abstract AbstractProductA createProductA(); abstract AbstractProductB createProductB(); } class ConcreteFactory1 extends AbstractFactory{ AbstractProductA createProductA(){ return new ProductA1("ProductA1"); } AbstractProductB createProductB(){ return new ProductB1("ProductB1"); } } class ConcreteFactory2 extends AbstractFactory{ AbstractProductA createProductA(){ return new ProductA2("ProductA2"); } AbstractProductB createProductB(){ return new ProductB2("ProductB2"); } } //Factory creator - an indirect way of instantiating the factories class FactoryMaker{ private static AbstractFactory pf=null; static AbstractFactory getFactory(String choice){ if(choice.equals("a")){ pf=new ConcreteFactory1(); }else if(choice.equals("b")){ pf=new ConcreteFactory2(); } return pf; } } // Client public class Client{ public static void main(String args[]){ AbstractFactory pf=FactoryMaker.getFactory("a"); AbstractProductA product=pf.createProductA(); //more function calls on product } }FactoryMaker類使用的是簡單工廠模式,而具體工廠的實現用的是工廠方法模式。
適用場景
1. 一個系統要獨立於它的產品的創建、組合和表示時。
2. 一個系統要由多個產品系列中的一個來配置時。
3. 需要強調一系列相關的產品對象的設計以便進行聯合使用時。
4. 提供一個產品類庫,而只想顯示它們的接口而不是實現時。
優點
1. 具體產品從客戶代碼中被分離出來
2. 容易改變產品的系列
3. 將一個系列的產品族統一到一起創建
缺點
1. 在產品族中擴展新的產品是很困難的,它需要修改抽象工廠的接口和具體工廠。