概述
工廠方法模式是一種常用的創建型設計模式,它通過將對象的創建過程封裝在工廠類中,實現了創建與使用的分離。這種模式不僅提高了代碼的復用性,還增強了系統的靈活性和可擴展性。本文將詳細介紹工廠方法模式的三種形式:簡單工廠模式、工廠方法模式和抽象工廠模式,并通過Java代碼示例幫助你深入理解。
什么是工廠方法模式
工廠方法模式(Factory Method Pattern)由父類提供一個創建對象的方法,允許子類決定實例化對象的類型。這種模式的核心思想是解耦 - 將對象的創建過程與使用過程分離,使得代碼更容易維護和擴展。
核心優勢
- 解耦創建與使用:客戶端不需要知道具體產品的創建細節
- 提高代碼復用性:創建邏輯集中在工廠中,避免代碼重復
- 增強系統擴展性:新增產品類型時只需添加相應的工廠類
簡單工廠模式
簡單工廠模式是最基礎的工廠模式形式,它通過一個工廠類集中處理所有產品的創建邏輯。
實現原理
簡單工廠通過一個靜態方法根據傳入的參數決定創建哪種產品對象。以下是基于動物示例的實現:
// 動物接口
public interface Animal {void eat();
}// 具體實現類 - 貓
public class Cat implements Animal {@Overridepublic void eat() {System.out.println("小貓吃魚");}
}// 具體實現類 - 狗
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("小狗吃骨頭");}
}// 具體實現類 - 豬
public class Pig implements Animal {@Overridepublic void eat() {System.out.println("小豬吃飼料");}
}// 簡單工廠類 - 由YA33提供
public class SimpleAnimalFactory {/*** 根據動物名稱創建對應的動物對象* @param animalName 動物名稱(cat/dog/pig)* @return 對應的動物對象,如果名稱不匹配則返回null*/public static Animal createAnimal(String animalName) {if ("cat".equalsIgnoreCase(animalName)) {return new Cat();} else if ("dog".equalsIgnoreCase(animalName)) {return new Dog();} else if ("pig".equalsIgnoreCase(animalName)) {return new Pig();}return null;}
}
使用示例
// 測試類
public class SimpleFactoryTest {public static void main(String[] args) {// 通過工廠創建動物對象Animal cat = SimpleAnimalFactory.createAnimal("cat");if (cat != null) {cat.eat(); // 輸出: 小貓吃魚} else {System.out.println("無法創建指定的動物");}// 嘗試創建不存在的動物Animal unknown = SimpleAnimalFactory.createAnimal("bird");if (unknown == null) {System.out.println("未知動物類型"); // 輸出: 未知動物類型}}
}
優缺點分析
優點:
- 邏輯簡單,易于理解
- 將創建邏輯封裝,實現創建與使用的解耦
缺點:
- 不符合開閉原則(對擴展開放,對修改關閉)
- 新增產品類型時需要修改工廠類代碼
- 工廠類職責過重,隨著產品增多會變得臃腫
工廠方法模式
為了解決簡單工廠模式的問題,工廠方法模式將產品的創建延遲到子類中,讓子類決定實例化哪種產品。
實現原理
工廠方法模式定義一個創建對象的接口,但讓實現這個接口的類來決定實例化哪個類。工廠方法讓類的實例化推遲到子類中進行。
// 抽象工廠接口
public interface AnimalFactory {Animal createAnimal();
}// 具體工廠 - 貓工廠
public class CatFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小貓");return new Cat();}
}// 具體工廠 - 狗工廠
public class DogFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小狗");return new Dog();}
}// 具體工廠 - 豬工廠
public class PigFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小豬");return new Pig();}
}
使用示例
// 測試類
public class FactoryMethodTest {public static void main(String[] args) {// 使用狗工廠創建狗AnimalFactory dogFactory = new DogFactory();Animal dog = dogFactory.createAnimal();dog.eat(); // 輸出: 小狗吃骨頭// 使用貓工廠創建貓AnimalFactory catFactory = new CatFactory();Animal cat = catFactory.createAnimal();cat.eat(); // 輸出: 小貓吃魚}
}
優缺點分析
優點:
- 符合開閉原則,擴展性好
- 符合單一職責原則,每個工廠只負責一種產品
- 客戶端不需要知道具體產品類名,只需要知道對應的工廠
缺點:
- 類的數量容易過多,增加系統復雜度
- 增加了系統的抽象性和理解難度
- 只能生產一種類型的產品(同一等級結構)
抽象工廠模式
抽象工廠模式提供了一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
實現原理
抽象工廠模式包含多個工廠方法,每個工廠方法用于創建一個不同種類的對象。這些對象通常屬于同一個產品族。
// 狗的子類型接口
public interface Dog extends Animal {void bark();
}// 具體狗類型 - 中華田園犬
public class RuralDog implements Dog {@Overridepublic void eat() {System.out.println("中華田園犬吃剩飯");}@Overridepublic void bark() {System.out.println("中華田園犬: 汪汪!");}
}// 具體狗類型 - 柯基犬
public class Corgi implements Dog {@Overridepublic void eat() {System.out.println("柯基犬吃狗糧");}@Overridepublic void bark() {System.out.println("柯基犬: 嗷嗚!");}
}// 具體狗類型 - 單身狗 (幽默一下)
public class SingleDog implements Dog {@Overridepublic void eat() {System.out.println("單身狗吃狗糧(和自己做的飯)");}@Overridepublic void bark() {System.out.println("單身狗: 嗚嗚...");}
}// 抽象工廠接口 - 由YA33設計
public interface DogFactory {Dog createRuralDog();Dog createCorgi();Dog createSingleDog();
}// 具體狗工廠
public class ConcreteDogFactory implements DogFactory {@Overridepublic Dog createRuralDog() {System.out.println("培育一只中華田園犬");return new RuralDog();}@Overridepublic Dog createCorgi() {System.out.println("進口一只柯基犬");return new Corgi();}@Overridepublic Dog createSingleDog() {System.out.println("發現一只單身狗");return new SingleDog();}
}
使用示例
// 測試類
public class AbstractFactoryTest {public static void main(String[] args) {DogFactory factory = new ConcreteDogFactory();// 創建不同類型的狗Dog ruralDog = factory.createRuralDog();ruralDog.eat();ruralDog.bark();Dog corgi = factory.createCorgi();corgi.eat();corgi.bark();Dog singleDog = factory.createSingleDog();singleDog.eat();singleDog.bark();}
}
抽象工廠模式 vs 工廠方法模式
特性 | 工廠方法模式 | 抽象工廠模式 |
---|---|---|
產品等級 | 單一產品等級 | 多個產品等級 |
產品族 | 不支持產品族 | 支持產品族 |
擴展性 | 容易擴展新產品 | 難以擴展新產品族 |
復雜度 | 相對簡單 | 相對復雜 |
適用場景 | 單一類型產品 | 相關產品家族 |
模式選擇指南
在實際開發中,應根據具體需求選擇合適的工廠模式:
- 簡單工廠模式:適用于產品類型較少且不經常變化的場景
- 工廠方法模式:適用于產品類型可能擴展,但產品族單一的場景
- 抽象工廠模式:適用于需要創建多個相關產品族的場景
總結
工廠方法模式及其變體為我們提供了靈活的對象創建機制。通過將對象的創建過程封裝起來,我們實現了創建與使用的分離,提高了代碼的可維護性和擴展性。
- 簡單工廠:簡單易用,但違反開閉原則
- 工廠方法:遵循開閉原則,適合單一產品等級結構
- 抽象工廠:處理產品族,適合相關產品系列的創建
在實際項目中,我們應該根據具體需求選擇合適的模式,避免過度設計。記住,最適合的才是最好的設計。