06、Java模式--工廠模式
工廠模式
在日常開發中,凡是需要生成複雜物件的地方,都可以嘗試考慮使用工廠模式來代替。
工廠模式有 3 種不同的實現方式,分別是簡單工廠模式、工廠方法模式和抽象工廠模式。
簡單工廠模式
在簡單工廠模式中建立例項的方法通常為靜態(static)方法,因此簡單工廠模式(Simple Factory Pattern)又叫作靜態工廠方法模式(Static Factory Method Pattern)。
簡單工廠模式每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,這增加了系統的複雜度,違背了開閉原則。
簡單工廠優缺點
優點:
工廠類包含必要的邏輯判斷,可以決定在什麼時候建立哪一個產品的例項。
客戶端無需知道所建立具體產品的類名,只需知道引數即可。
也可以引入配置檔案,在不修改客戶端程式碼的情況下更換和新增新的具體產品類。
缺點:
簡單工廠模式的工廠類單一,負責所有產品的建立,職責過重,異常會讓整個系統受影響
使用簡單工廠模式會增加系統中類的個數(引入新的工廠類),增加系統的複雜度和理解難度。
系統擴充套件困難,一旦增加新產品不得不修改工廠邏輯,在產品型別較多時,可能造成邏輯過於複雜。
簡單工廠模式使用了 static 工廠方法,造成工廠角色無法形成基於繼承的等級結構。
對於產品種類相對較少的情況,考慮使用簡單工廠模式。使用簡單工廠模式的客戶端只需要傳入工廠類的引數,不需要關心如何建立物件的邏輯,可以很方便地建立所需產品。
模式的結構
簡單工廠模式的主要角色如下:
- 簡單工廠(SimpleFactory):是簡單工廠模式的核心,負責實現建立所有例項的內部邏輯。
- 抽象產品(Product):是簡單工廠建立的所有物件的父類,負責描述所有例項共有的公共介面。
- 具體產品(ConcreteProduct):是簡單工廠模式的建立目標。
其結構圖如下圖所示:
模式的實現
根據上圖寫出該模式的程式碼如下:
public class Client { // 抽象產品 public interface Product{ void show(); } // 具體產品A static class ConcreteProduct1 implements Product { @Override public void show() { System.out.println("具體產品1顯示..."); } } // 具體產品B static class ConcreteProduct2 implements Product { @Override public void show() { System.out.println("具體產品2顯示..."); } } // 簡單工廠類,用於生成產品 static class SimpleFactory{ static final int PRODUCT_A = 0; static final int PRODUCT_B = 1; public static Product makeProduct(int kind){ switch (kind){ case PRODUCT_A: return new ConcreteProduct1(); case PRODUCT_B: return new ConcreteProduct2(); } return null; } } }
測試程式碼如下所示:
public class Client {
public static void main(String[] args) {
Client.Product product1 = Client.SimpleFactory.makeProduct(0);
Client.Product product2 = Client.SimpleFactory.makeProduct(1);
product1.show();
product2.show();
}
}
工廠方法模式
工廠方法模式”是對簡單工廠模式的進一步抽象化,其好處是可以使系統在不修改原來程式碼的情況下引進新的產品,即滿足開閉原則。
優點:
使用者只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體建立過程。
靈活性增強,對於新產品的建立,只需多寫一個相應的工廠類。
典型的解耦框架。高層模組只需要知道產品的抽象類,無須關心其他實現類。
缺點:
- 類的個數容易過多,增加複雜度
- 增加了系統的抽象性和理解難度
- 抽象產品只能生產一種產品,此弊端可使用抽象工廠模式解決。
模式的結構
工廠方法模式的主要角色如下。
抽象工廠(Abstract Factory):提供了建立產品的介面,呼叫者通過它訪問具體工廠的工廠方法 newProduct() 來建立產品。
具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的建立。
抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能。
具體產品(ConcreteProduct):實現了抽象產品角色所定義的介面,由具體工廠來建立,它同具體工廠之間一一對應。
其結構圖如下圖所示:
模式實現
上述UML類圖的實現如下:
// 抽象產品
public interface Product {
void show();
}
// 具體產品1
public class ConcreteProduct1 implements Product{
@Override
public void show() {
System.out.println("具體產品1顯示...");
}
}
// 具體產品2
public class ConcreteProduct2 implements Product{
@Override
public void show() {
System.out.println("具體產品2顯示...");
}
}
// 抽象工廠
public interface AbstractFactory {
Product newProduct();
}
// 具體工廠1
public class ConcreteFactory1 implements AbstractFactory{
@Override
public Product newProduct() {
System.out.println("具體工廠1生成-->具體產品1...");
return new ConcreteProduct1();
}
}
// 具體工廠2
public class ConcreteFactory2 implements AbstractFactory{
@Override
public Product newProduct() {
System.out.println("具體工廠2生成-->具體產品1...");
return new ConcreteProduct2();
}
}
編寫測試類進行測試工廠方法模式:
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
Product product1 = factory1.newProduct();
product1.show();
AbstractFactory factory2 = new ConcreteFactory2();
Product product2 = factory2.newProduct();
product2.show();
}
}
輸出結果如下所示:
具體工廠1生成-->具體產品1...
具體產品1顯示...
具體工廠2生成-->具體產品1...
具體產品2顯示...
注意:工廠方法模式只考慮生產單一產品的情況。
抽象工廠模式
抽象工廠(AbstractFactory)模式的定義:是一種為訪問類提供一個建立一組相關或相互依賴物件的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。
抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產一個等級的產品,而抽象工廠模式可生產多個等級的產品。
使用抽象工廠模式一般要滿足以下條件。
- 系統中有多個產品族,每個具體工廠建立同一族但屬於不同等級結構的產品。
- 系統一次只可能消費其中某一族產品,即同族的產品一起使用。
抽象工廠模式除了具有工廠方法模式的優點外,其他主要優點如下
- 可以在類的內部對產品族中相關聯的多等級產品共同管理,而不必專門引入多個新的類來進行管理。
- 當需要產品族時,抽象工廠可以保證客戶端始終只使用同一個產品的產品組。
- 抽象工廠增強了程式的可擴充套件性,當增加一個新的產品族時,不需要修改原始碼,滿足開閉原則。
其缺點是:當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。增加了系統的抽象性和理解難度。
模式的結構
抽象工廠模式的主要角色如下。
抽象工廠(Abstract Factory):提供了建立產品的介面,它包含多個建立產品的方法 newProduct(),可以建立多個不同等級的產品。
具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的建立。
抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
具體產品(ConcreteProduct):實現了抽象產品角色所定義的介面,由具體工廠來建立,它同具體工廠之間是多對一的關係。
抽象工廠模式的結構圖如圖所示:
模式的實現
抽象工廠模式的結構同工廠方法模式的結構相似,不同的是其產品的種類不止一個,所以建立產品的方法也不止一個。
(1) 抽象產品
public interface Product1 {
void show();
}
public interface Product2 {
void show();
}
(2) 具體的產品
public class ConcreteProduct11 implements Product1 {
@Override
public void show() {
System.out.println("具體產品11顯示...");
}
}
public class ConcreteProduct12 implements Product1 {
@Override
public void show() {
System.out.println("具體產品12顯示...");
}
}
public class ConcreteProduct21 implements Product2 {
@Override
public void show() {
System.out.println("具體產品21顯示...");
}
}
public class ConcreteProduct22 implements Product2 {
@Override
public void show() {
System.out.println("具體產品22顯示...");
}
}
(3) 定義抽象工廠
public interface AbstractFactory {
Product1 newProduct1();
Product2 newProduct2();
}
(4) 抽象工廠的實現類,也就是具體的工廠類
public class ConcreteFactory1 implements AbstractFactory{
@Override
public Product1 newProduct1() {
System.out.println("具體工廠 1 生成-->具體產品 ConcreteProduct11...");
return new ConcreteProduct11();
}
@Override
public Product2 newProduct2() {
System.out.println("具體工廠 1 生成-->具體產品 ConcreteProduct21...");
return new ConcreteProduct21();
}
}
public class ConcreteFactory2 implements AbstractFactory{
@Override
public Product1 newProduct1() {
System.out.println("具體工廠 2 生成-->具體產品 ConcreteProduct11...");
return new ConcreteProduct11();
}
@Override
public Product2 newProduct2() {
System.out.println("具體工廠 2 生成-->具體產品 ConcreteProduct22...");
return new ConcreteProduct22();
}
}
(5) 測試的程式碼如下:
public class Client {
public static void main(String[] args){
AbstractFactory factory1 = new ConcreteFactory1();
Product1 product1 = factory1.newProduct1();
product1.show();
AbstractFactory factory2 = new ConcreteFactory2();
Product2 product4 = factory2.newProduct2();
product4.show();
}
}
輸出結果如下:
具體工廠 1 生成-->具體產品 ConcreteProduct11...
具體產品11顯示...
具體工廠 2 生成-->具體產品 ConcreteProduct22...
具體產品22顯示...
和抽象方法模式區別在於抽象工廠生成的產品不再單一。當系統中只存在一個等級結構的產品時,抽象工廠模式將退化到工廠方法模式。