设计模式:工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
歡迎跳轉到本文的原文鏈接:https://honeypps.com/design_pattern/factory/
?在面向對象編程中, 最通常的方法是一個new操作符產生一個對象實例,new操作符就是用來構造對象實例的。但是在一些情況下, new操作符直接生成對象會帶來一些問題。舉例來說, 許多類型對象的創造需要一系列的步驟: 你可能需要計算或取得對象的初始設置; 選擇生成哪個子對象實例; 或在生成你需要的對象之前必須先生成一些輔助功能的對象。 在這些情況,新對象的建立就是一個 “過程”,不僅是一個操作,像一部大機器中的一個齒輪傳動。
##分類
?工廠模式主要是為創建對象提供過渡接口,以便將創建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的。
?工廠模式可以分為三類:
?這三種模式從上到下逐步抽象,并且更具一般性。
?GOF在《設計模式》一書中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory)。將簡單工廠模式(Simple Factory)看為工廠方法模式的一種特例,兩者歸為一類。
##簡單工廠模式
?簡單工模式時類的創建模式,又叫做靜態工廠方法(static Factory Method)。簡單工廠模式是一個工廠對象決定創建出哪一種產品類的實例。它存在的目的很簡單:定義一個創建對象的接口。
?組成:
?舉個簡單例子:
1 抽象產品角色
2 具體產品角色(可以把方法定義為static的)
public class ProductA implements IProduct {@Overridepublic void method(){System.out.println("I'm ProductA!");} }public class ProductB implements IProduct {@Overridepublic void method(){System.out.println("I'm ProductB!");} }3 工廠類角色
public class SimpleFactory {public IProduct produce(String type){if("A".equals(type)){return new ProductA();}else if("B".equals(type)){return new ProductB();}else{System.out.println("請輸入正確的類型");return null;}} }4 測試類
public class MainTest {public static void main(String args[]){SimpleFactory factory = new SimpleFactory();IProduct product = factory.produce("A");product.method();} }輸出:I’m ProductA!
?在Java中java.text.DateFormat就是簡單工廠模式的典型案例。
優點:專門定義一個工廠類負責創建其他類的實例,最大的優點在于工廠類中包含了必要的邏輯,根據客戶需要的條件動態實例化相關的類。
缺點:當需要增加一種產品時,比如ProductC就需要修改簡單工廠類SimpleFactory(增加if-else塊),這違背了開閉原則。
TIPS
?其實如果采用反射機制實現簡單工廠并沒有違背開閉原則。
?利用反射機制,將簡單工廠類改成:
?測試類:
public class MainTest {public static void main(String args[]) throws Exception{SimpleFactory factory = new SimpleFactory();IProduct product = factory.produce(ProductA.class);product.method();} }?這樣當有新的產品時,其實并不需要修改工廠類。《Effective Java(Second Edition)》中明確指出:**通常,普通應用程序在運行時不應該以反射方式訪問對象。**所以本篇文章建立在不采用反射機制的情況下,在下面介紹的工廠方法模式其實也可以改用反射機制實現,博主就不展示了。至于《Effective Java(Second Edition)》為什么不推薦反射機制,可以參考此書的“接口優先于反射機制”這一主題,這里不贅述。
##工廠方法模式
?工廠方法模式是簡單工廠模式的進一步抽象化和推廣,工廠方法模式里不再只由一個工廠類決定那一個產品類應當被實例化,這個決定被交給抽象工廠的子類去做。
?來看下它的組成:
?舉個簡單例子:
1 抽象工廠角色
2 具體工廠角色
public class ConcreteFactoryA implements IFactory {@Overridepublic IProduct produce(){return new ProductA();} }public class ConcreteFactoryB implements IFactory {@Overridepublic IProduct produce(){return new ProductB();} }3 抽象產品角色(和簡單工廠的一樣)
public interface IProduct {public void method(); }4 具體產品角色(和簡單工廠的一樣)
public class ProductA implements IProduct {@Overridepublic void method(){System.out.println("I'm ProductA!");} }public class ProductB implements IProduct {@Overridepublic void method(){System.out.println("I'm ProductB!");} }5 測試代碼:
public class MainTest {public static void main(String[] args){IFactory factoryA = new ConcreteFactoryA();IProduct product1 = factoryA.produce();product1.method();} }輸出:I’m ProductA!
工廠方法模式和簡單工廠模式在定義上的不同是很明顯的。工廠方法模式的核心是一個抽象工廠類,而不像簡單工廠模式, 把核心放在一個實類上。工廠方法模式可以允許很多實的工廠類從抽象工廠類繼承下來, 從而可以在實際上成為多個簡單工廠模式的綜合,從而推廣了簡單工廠模式。
工廠方法相比于簡單工廠模式的優點是增加一個產品,只需要增加一個具體工廠類和具體產品類,沒有修改原先的工廠類,符合開閉原則。缺點是客戶端的代碼會需要修改(簡單工廠模式的客戶端不需要修改),隨著產品的繼續增加,所要實現的類的個數也會隨之增大。
##抽象工廠模式
?在抽象工廠模式中,抽象產品 (AbstractProduct) 可能是一個或多個,從而構成一個或多個產品族(Product Family)。 在只有一個產品族的情況下,抽象工廠模式實際上退化到工廠方法模式。
工廠方法模式 VS 抽象工廠模式
?工廠方法模式:一個抽象產品類,可以派生出多個具體產品類。每個具體工廠類只能創建一個具體產品類的實例。
?抽象工廠模式:多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。一個抽象工廠類可以派生出多個具體工廠類。每個具體工廠類可以創建多個具體產品的實例。
?區別:工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個。
舉個簡單例子:
1 抽象產品角色
2 抽象工廠角色
public interface AbstractFactory {public AbstractProductA CreateProductA();public AbstractProductB CreateProductB(); }3 具體產品角色
public class ProductA1 implements AbstractProductA {@Overridepublic void produceA(){System.out.println("Im ProductA1!");} } public class ProductA2 implements AbstractProductA {@Overridepublic void produceA(){System.out.println("Im ProductA2!");} } public class ProductB1 implements AbstractProductB {@Overridepublic void produceB(){System.out.println("Im ProductB1!");} } public class ProductB2 implements AbstractProductB {@Overridepublic void produceB(){System.out.println("Im ProductB2!");} }4 具體工廠角色
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA CreateProductA(){return new ProductA1();}@Overridepublic AbstractProductB CreateProductB(){return new ProductB1();} } public class ConcreteFactory2 implements AbstractFactory {@Overridepublic AbstractProductA CreateProductA(){return new ProductA2();}@Overridepublic AbstractProductB CreateProductB(){return new ProductB2();} }5 測試代碼
public class MainTest {public static void main(String[] args){AbstractFactory factory = new ConcreteFactory1();AbstractProductA product1 = factory.CreateProductA();AbstractProductB product2 = factory.CreateProductB();product1.produceA();product2.produceB();} }輸出結果:
Im ProductA1! Im ProductB1!?抽象工廠的優點:抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的內部對產品族進行約束。所謂的產品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類內部對產品族的關聯關系進行定義和描述,而不必專門引入一個新的類來進行管理。
?抽象工廠的缺點:產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。所以使用抽象工廠模式時,對產品等級結構的劃分是非常重要的。
Jdk中的工廠方法
java.lang.Object#toString();
java.lang.Class#newInstance();
java.lang.Class#forName();
java.lang.Boolean#valueOf();
java.lang.Proxy#newProxyInstance();
java.lang.reflect.Array#newInstance();
java.lang.reflect.Constructor#newInstance();
java.util.concurrent.Executors#newCachedThreadPool()等
##總結
?無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬于工廠模式,在形式和特點上也是極為相似的,他們的最終目的都是為了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因為他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法后,由于類中的產品構成了不同等級結構中的產品族,它就變成抽象工廠模式了;而對于抽象工廠模式,當減少一個方法使的提供的產品不再構成產品族之后,它就演變成了工廠方法模式。所以,在使用工廠模式時,只需要關心降低耦合度的目的是否達到了。
參考資料:
歡迎跳轉到本文的原文鏈接:https://honeypps.com/design_pattern/factory/
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
總結
以上是生活随笔為你收集整理的设计模式:工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式:开篇
- 下一篇: asp.net ajax控件工具集 Au