直接 new A() 存在三大痛點:
工廠模式核心思想:將「創建」與「使用」分離,封裝實例化細節。
public class Factory {
public static Sample create(int type) {
if (type == 1) return new SampleA();
else if (type == 2) return new SampleB();
throw new IllegalArgumentException();
}
}
// 使用
Sample s = Factory.create(1);
優點:調用者不依賴具體類。缺點:新增產品需修改工廠類(違反開閉),邏輯集中膨脹。
定義抽象工廠接口,子類決定實例化哪個具體產品:
interface Factory { Sample create(); }
class FactoryA implements Factory { public Sample create() { return new SampleA(); } }
class FactoryB implements Factory { public Sample create() { return new SampleB(); } }
Class.forName() 實例化
public abstract class ForumFactory {
private static ForumFactory factory;
public static ForumFactory getInstance(Authorization auth) {
if (factory == null) synchronized(initLock) {
if (factory == null) {
Class c = Class.forName("com.jivesoftware.forum.database.DbForumFactory");
factory = (ForumFactory) c.newInstance();
}
}
return new ForumFactoryProxy(auth, factory, ...); // Proxy 模式控制權限
}
public abstract Forum createForum(String name, String desc);
}
亮點:單例 + 工廠方法 + 動態加載 + 動態代理 多模式協作,實現存儲引擎熱插拔(數據庫/文件系統)與權限控制。
public class CatalogDAOFactory {
public static CatalogDAO getDAO() {
String className = (String) new InitialContext().lookup("CATALOG_DAO_CLASS");
return (CatalogDAO) Class.forName(className).newInstance();
}
}
JNDI 注入實現類名,零代碼修改切換數據庫實現。
當系統需要創建多個相關/依賴的產品族時(如 Sample + Sample2),且不同族內部有關聯約束:
abstract class AbstractFactory {
abstract Sample createSample();
abstract Sample2 createSample2();
}
class SimpleFactory extends AbstractFactory {
Sample createSample() { return new SampleA(); }
Sample2 createSample2() { return new Sample2A(); } // 簡單工藝族
}
class BombFactory extends AbstractFactory {
Sample createSample() { return new SampleB(); }
Sample2 createSample2() { return new Sample2B(); } // 複雜工藝族
}
關鍵差異:
| 場景 | 推薦模式 | 理由 |
|---|---|---|
| 創建邏輯固定、產品單一、無擴展需求 | 簡單工廠 | 簡單直接 |
| 產品單一但頻繁擴展、需解耦創建邏輯 | 工廠方法 | 開閉原則、動態加載友好 |
| 需創建一組相關產品、族內有約束、需整體切換 | 抽象工廠 | 保證族內一致性 |