相關概念:
抽象工廠方法模式是工廠方法模式的一個特例。
**定義:**工廠方法模式(FACTORY METHOD)是一種常用的對象創建型設計模式,此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦、復用和方便后期維護拓展的目的。它的核心結構有四個角色,分別是抽象工廠;具體工廠;抽象產品;具體產品。
**抽象工廠(Creator):**是工廠方法模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現這個接口。
**具體工廠(Concrete Creator):**這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,并且受到應用程序調用以創建產品對象。
**抽象產品(Product):**工廠方法模式所創建的對象的超類型,也就是產品對象的共同父類或共同擁有的接口。在上圖中,這個角色是Light。
**具體產品(Concrete Product):**這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應。
**抽象工廠方法模式:**為創建一組相關或者相互依賴的對象提供一個接口,而不需要指定它們的具體類。每個抽象產品都對應一個或多個具體的產品,每個抽象工廠都對應一個或多個具體工廠,包含四個基本角色。
適用場景:
1.
作為一種創建類模式,在任何需要生成復雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是復雜對象適合使用工廠模式,而簡單對象,特別是只需要通過new就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的復雜度。
1.
工廠模式是一種典型的解耦模式,迪米特法則在工廠模式中表現的尤為明顯。假如調用者自己組裝產品需要增加依賴關系時,可以考慮使用工廠模式。將會大大降低對象之間的耦合度。
1.
由于工廠模式是依靠抽象架構的,它把實例化產品的任務交由實現類完成,擴展性比較好。也就是說,當需要系統有比較好的擴展性時,可以考慮工廠模式,不同的產品用不同的實現工廠來組裝。
工廠方法模式和Builder模式的異同:
1.
這兩種模式都是為了創建復雜對象而設計的模式
1.
工廠方法模式用來生成一系列同類型的復雜對象(如:汽車生產工廠生產汽車),復雜對象的創建過程在工廠方法中,并且可以管理一系列的生成的產品等,當一個工廠只生產一種類型的產品,生產出來的產品類型相同。
1.
Builder模式是用來生成一個更為復雜對象(這種類型的對象具有不同的表現),將復雜對象的創建與展示相分離,將對象的創建過程封裝以向外界隱藏起來,使得同樣的構建過程可以創建不同的表示。
實現代碼:
抽象產品
~~~
/**
* 抽象產品
* @author lt
*
*/
public abstract class Product {
/**
* 每個產品都應該有它的用途
*/
public abstract void use();
}
~~~
抽象工廠
~~~
/**
* 抽象工廠
* @author lt
*
*/
public abstract class Factory {
/**
* Product是要生成的產品的一個抽象類,即抽象產品
* @return Product
*/
public abstract Product createProduct();
}
~~~
具體產品
~~~
/**
* 具體產品
* @author lt
*
*/
public class Car extends Product{
protected void run(){
System.out.println("汽車跑起來了");
}
protected void stop(){
System.out.println("汽車停下來了");
}
@Override
public void use() {
System.out.println("一種交通工具");
}
}
~~~
具體工廠
~~~
/**
* 具體工廠,這里是汽車生產工廠
* @author lt
*
*/
public class CarFactory extends Factory{
/**
* Car是具體產品,是產品的一個子類
* @return
*/
@Override
public Car createProduct() {
return new Car();
}
}
~~~
具體工廠里面可以封裝一些產品創建過程中需要做的操作,如:將生產的產品添加到一個集合中,以便后期管理。
**測試:**
~~~
public static void main(String[] args) {
Factory factory = new CarFactory();
Car car = (Car) factory.createProduct();
car.use();
car.run();
car.stop();
}
~~~
?可以看到這里的工廠是抽象工廠(接口),但實際上是具體的工廠(實例),那么它實際生產出來的產品也是具體產品(讓子類決定實例化哪一個類,工廠方法使一個類的實例化延遲到其子類),這里的具體產品是汽車。
**結果:**

上面的這些代碼是工廠方法模式的完整的形式,工廠方法的完整描述:定義一個創建對象的接口(即抽象工廠類)實例化抽象類(抽象產品),讓其子類(具體工廠類)決定實例化哪一個類(具體產品類)。“一對一”的關系。,由四個角色組成。
除了上面的四個角色組成的工廠方法模式外,還有簡單工廠方法模式或者說是靜態工廠方法模式。
我們對上面的代碼進行一些改造
在具體工廠CarFactory中添加一個方法:
~~~
public <T extends Object> T createCar(Class<T> clazz){
T obj = null;
try {
obj = (T) Class.forName(clazz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
~~~
-
也可以為每一種具體的汽車寫一個生產方法,這里為了簡單起見,利用反射根據傳遞進來的類字節碼生成類(具體產品)的實例。
-
如果這個方法寫成靜態`static`的,那么這個工廠就是簡單工廠或者靜態工廠了,相應的模式為簡單工廠方法模式或靜態工廠方法模式。
具體產品A,寶馬汽車
~~~
/**
* 具體產品,寶馬汽車
* @author lt
*
*/
public class BaoMa extends Car{
@Override
protected void run() {
System.out.println("寶馬跑起來了!");
}
@Override
protected void stop() {
System.out.println("寶馬停下來了!");
}
}
~~~
具體產品B,奔馳汽車
~~~
/**
* 具體產品,大奔
* @author lt
*
*/
public class BenChi extends Car{
@Override
protected void run() {
System.out.println("奔馳跑起來了!");
}
@Override
protected void stop() {
System.out.println("奔馳停下來了!");
}
}
~~~
**測試:**
~~~
public static void main(String[] args) {
CarFactory factory = new CarFactory();
BaoMa baoma = factory.createCar(BaoMa.class);
baoma.run();
baoma.stop();
BenChi benchi = factory.createCar(BenChi.class);
benchi.run();
benchi.stop();
}
~~~
**結果:**

最簡單的一個工廠方法模式是靜態工廠方法模式,即不含有任何抽象,相應的方法為static的,這個模式在Android開發中用一個工廠管理多個Fragment的時候用到過。
### 總結:
工廠方法模式中的抽象工廠方法模式具有如下優缺點:
抽象工廠方法模式優點:
1.
分離接口與實現,耦合性低。要客戶端使用抽象工廠來創建需要的對象,如客戶端不需要知道具體的實現是誰,客戶端只是面向接口編程,使其在具體的產品實現中解耦。
1.
靈活性高,極易擴展。由于是基于接口與實現的分分離,使得抽象工廠方法模式在切換同類型的產品類的時候更加靈活,更加簡單。
抽象工廠方法模式缺點:
1.
類文件爆炸性增加。每當有一個具體產品與其他具體產品不同時都需要對應的一個具體工廠。
1.
不太容易擴展新類型的產品。因為我們增加一個新類型的產品類時候就需要修改抽象工廠,抽象工廠更改后,那么對應的具體的工廠類均要被修改,甚至當新類型的產品類和原來的產品類截然不同時,就需要一個添加一個新的抽象工廠。