在物件導向設計中,new 關鍵字雖然是建立物件最直接的方式,但隨著系統複雜度提升,直接實例化具體類別會導致高耦合、難維護、難擴展。工廠模式透過封裝物件建立邏輯,為「創建者」與「使用者」之間引入一層間接關係,實現解耦。本文將系統梳理 Java 三大經典工廠模式:簡單工廠、工廠方法 與 抽象工廠,並透過代碼範例解析其適用場景與優缺點。
根據《Java 與模式》歸納,工廠模式主要適用於以下情境:
static 方法)。// 抽象產品
public interface Car { void drive(); }
// 具體產品
public class Benz implements Car { public void drive() { System.out.println("Driving Benz"); } }
public class Bmw implements Car { public void drive() { System.out.println("Driving Bmw"); } }
// 簡單工廠
public class Driver {
public static Car driverCar(String type) throws Exception {
if ("Benz".equalsIgnoreCase(type)) return new Benz();
else if ("Bmw".equalsIgnoreCase(type)) return new Bmw();
else throw new Exception("不支援的車型");
}
}
// 客戶端
public class Magnate {
public static void main(String[] args) throws Exception {
Car car = Driver.driverCar("Benz");
car.drive();
}
}
適用場景:業務簡單、產品種類固定、擴展頻率低的場合。
Driver 介面)。BenzDriver、BmwDriver)。// 抽象工廠
public interface Driver { Car driverCar(); }
// 具體工廠
public class BenzDriver implements Driver { public Car driverCar() { return new Benz(); } }
public class BmwDriver implements Driver { public Car driverCar() { return new Bmw(); } }
// 客戶端
public class Magnate {
public static void main(String[] args) {
Driver driver = new BenzDriver(); // 可動態注入
Car car = driver.driverCar();
car.drive();
}
}
改良建議:對於同層級的「兄弟產品」(如同品牌不同車系),可在具體工廠內部結合簡單工廠邏輯,減少類別數量。
位於不同產品等級結構中、功能相關聯的產品組成的家族。例如:
BenzSportsCar + BmwSportsCar = 跑車族
BenzBusinessCar + BmwBusinessCar = 商務車族
與工廠方法類似,但抽象工廠介面宣告多個創建方法,分別對應不同等級的產品(如 createSportsCar()、createBusinessCar())。具體工廠實現這組方法,確保產出的物件屬於同一族。
| 模式 | 抽象層次 | 擴展性 | 適用場景 |
|---|---|---|---|
| 簡單工廠 | 低 | 差(違反 OCP) | 產品固定、邏輯簡單、無頻繁擴展 |
| 工廠方法 | 中 | 良(符合 OCP) | 單一產品等級、需頻繁新增產品類型 |
| 抽象工廠 | 高 | 良(族內擴展) | 多產品等級、存在產品族、需保證族內一致性 |
最佳實踐:實際專案中常採用混合策略——頂層用抽象工廠定義產品族介面,具體工廠內部對同層級產品採用簡單工廠邏輯,兼顧擴展性與類別數量控制。
工廠模式的本質是將「變化」封裝起來。選型時請問自己:什麼在變?是產品種類?產品族?還是初始化邏輯?針對變化點選擇適當抽象層次,切勿過度設計。