Java設計模式-工廠模式
- 2020 年 1 月 3 日
- 筆記
簡單來說工廠模式就是幫助我們創建對象,隱藏了對象創建過程的複雜度(如類B需要調用類A,工廠類提供A類的創建介面,B只需要調用介面傳入相應參數即可)、避免你辛苦的準備構造方法的參數。說白了–就是工廠提供產品給客戶(按照提供的方式不同分成三類:簡單工廠、工廠、抽象工廠) 具體簡介看下面:

工廠模式是我們最常用的實例化對象模式了,是用工廠方法代替new操作的一種模式。著名的Jive論壇 ,就大量使用了工廠模式,工廠模式在Java程式系統可以說是隨處可見。因為工廠模式就相當於創建實例對象的new,我們經常要根據類Class生成實例對象,如A a=new A() 工廠模式也是用來創建實例對象的,所以以後new時就要多個心眼,可以考慮是否使用工廠模式,雖然這樣做,可能多做一些工作,但會給你系統帶來更大的可擴展性和盡量少的修改量
角色
工廠模式有以下幾個角色(結合下面流程圖理解),產品即需要創建的實例對象
- 抽象產品類:所創建產品的父類,給出一個抽象介面或抽象類,以及一般由具體產品類具體實現。(多態的表現)— 如 Animal
- 具體產品類:抽象產品類的實現類,為實現某個具體產品的對象。 — 如 Dog
- 抽象工廠類:工廠提供創建產品的方法、工廠方法模式的核心(簡單工廠模式無此抽象類),與應用程式無關。是具體工廠必須實現的介面或者必須繼承的父類。
- 具體工廠類:繼承抽象工廠類,實現具體業務邏輯。
工廠模式和抽象工廠模式
圖解工廠模式和抽象工廠模式流程對比
工廠模式:

抽象工廠模式:

簡單工廠模式(靜態工廠方法)
含義:沒有抽象工廠類,由工廠類自身提供產品,程式碼如下
抽象產品類(抽象類或介面)
public interface IProduct{ void method(); }
具體產品實現類
//A產品 public class ProductA implement IProduct{ void method(){ logger.info("ProductA"); } } //B產品 public class ProductB implement IProduct{ void method(){ logger.info("ProductB"); } }
工廠類
public class Factory{ //簡單工廠模式 只有一個靜態方法提供產品所以也叫靜態工廠方法 public static IProduct createProduct(String productName){ if("A".equals("A"){ return new ProductA(); }else if("B".equals("B"){ return new ProductB(); }else } }
- 優點: 強調職責單一原則,一個類只提供一種功能
- 缺點: 一旦對工廠類修改就違反了開閉原則
工廠模式
工廠模式有一個抽象工廠類對應多個具體工廠實現類、一個抽象產品類對應一個具體實現類、並且每個具體工廠類只能創建一個具體產品類的實例
抽象產品類(抽象類或介面)
public interface IProduct{ void method(); }
具體產品實現類
//A產品 public class ProductA implement IProduct{ void method(){ logger.info("ProductA"); } } //B產品 public class ProductB implement IProduct{ void method(){ logger.info("ProductB"); } }
抽象工廠類(抽象類或介面)
public abstract class Factory{ /** *抽象工廠方法 *具體產生什麼由子類決定 *@return 具體產品對象 */ public abstract IProduct createProduct(); }
具體工廠類
//A工廠 public class AFactory extends Factory { //提供A產品 public IProduct createProduct(){ return new ProductA(); } } //B工廠 public class BFactory extends Factory { //提供B產品 public IProduct createProduct(){ return new ProductB(); } }
用法
Factory factory = new AFactory(); IProduct aProduct = factory.createProduct(); product.method();
- 優點:克服了簡單工廠違背開放-封閉原則的缺點,又保留了封裝對象創建過程的優點,降低客戶端和工廠的耦合性,所以說「工廠模式」是「簡單工廠模式」的進一步抽象和推廣
- 缺點:每增加一個產品,相應的也要增加一個子工廠,加大了額外的開發量。
抽象工廠模式
工廠模式有一個抽象工廠類對應多個具體工廠實現類、多個抽象產品類對應多個具體實現類、並且每個具體工廠類可以創建多個具體產品類的實例。
抽象產品類(抽象類或介面)
//飲料 public interface IDrink{ void method(); } //食物 public interface IFood{ void method(); }
具體產品實現類
//麵條 public class Noddle implement IFood{ void method(){ logger.info("麵條"); } } //米飯 public class Rice implement IFood{ void method(){ logger.info("米飯"); } } //可樂 public class Cola implement IDrink{ void method(){ logger.info("可樂"); } } //米飯 public class Sprite implement IDrink{ void method(){ logger.info("雪碧"); } }
抽象工廠類(抽象類或介面)
public abstract class Factory{ /** *抽象工廠方法 *具體產生什麼由子類決定 *@return 具體產品對象 */ public abstract IFood createFoodProduct(); public abstract IDrink createDrinkProduct(); }
具體工廠類
//A餐工廠(提供可樂和米飯) public class AFactory extends Factory{ //提供可樂 public IDrink createDrinkProduct(){ return new Cola(); } //提供米飯 public IFood createFoodProduct(){ return new Rice(); } } //B餐工廠(提供麵條和雪碧) public class BFactory extends Factory{ //提供麵條 public IFood createFoodProduct(){ return new Noddle(); } //提供雪碧 public IDrink createDrinkProduct(){ return new Sprite(); } }
用法
Factory factory = new AFactory(); IDrink cola = factory.createDrinkProduct(); cola.method(); IFood riceFood = factory.createFoodProduct(); riceFood.method();
- 優點
- 具有工廠方法模式解耦的優點。
- 工廠模式針對的是一個產品等級結構,抽象工廠模式針對的是面向多個產品等級結構的。 最主要的是可以在類內部對產品族的關聯關係進行定義和描述。
- 缺點
- 產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。
- 在具體工廠類的方法中,對於產品族裡的產品,只能使用其中一個。這也比較容易理解,比如,一個套餐不會包含兩款飲料(一款車子不可以搭載兩種空調)。
總結
有利有弊
優點:將對象的創建統一起來便於維護和整體把控,對擴展開放,對修改封閉 缺點:耦合性提高,由於工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中,這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模組功能的蔓延,對系統的維護和擴展非常不利。
使用有限
從工廠模式的示例可以看出:工廠模式需要類實現它的介面並且在業務內部存在明顯的繼承關係,比如汽車和Benz寶馬的關係。而繼承關係往往存在於模型之間,業務之間很難存在繼承關係,因此如果業務內部或者業務之間沒有這種顯式的繼承關係該咋辦?就算業務內部有繼承關係,各個業務交給你統一管理,這樣就會提高程式碼的耦合性,當創建邏輯複雜的時候,工廠方法就很複雜,容易產生干擾。
其開閉性優點很容易被替代
可以通過高度層次化和模組化來提高系統的開閉性,而不必生硬地去套用工廠模式。