想要動態創建不同風格的按鈕?想一鍵切換整個主題?工廠模式就是你的"生產流水線"!
想象一下這個場景:
你決定擴大奶茶店業務,推出兩個品牌系列:
- 經典系列:傳統珍珠奶茶,紅白配色
- 清新系列:水果茶,藍綠配色
每個系列都有自己風格的:
- 杯子設計
- 吸管樣式
- 包裝袋
- 會員卡
問題來了: 當顧客點單時,你如何確保:
- 經典系列的奶茶配經典杯+經典吸管+經典包裝?
- 清新系列的水果茶配清新杯+清新吸管+清新包裝?
- 避免經典杯配清新吸管這種"混搭事故"?
解決方案:建立兩個專屬工廠:
- 經典工廠:專門生產經典杯、經典吸管、經典包裝
- 清新工廠:專門生產清新杯、清新吸管、清新包裝
當顧客選擇系列后,你只需告訴對應的工廠:"給我一套裝備!"工廠就會返回風格一致的全套產品。
在Flutter中,這就是"抽象工廠模式"!而"工廠方法模式"則是它的靈活簡化版。
先理解基礎:工廠方法模式 (Factory Method)
核心思想: 定義一個創建對象的接口,但讓子類決定實例化哪個類。
Flutter場景: 根據條件創建不同類型的按鈕
// 按鈕產品接口
abstract class AppButton {Widget render(String text, VoidCallback onPressed);
}// 具體產品1:圓角按鈕
class RoundedButton implements AppButton { Widget render(String text, VoidCallback onPressed) {return ElevatedButton(style: ElevatedButton.styleFrom(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20),),onPressed: onPressed,child: Text(text),);}
}// 具體產品2:方形按鈕
class SquareButton implements AppButton { Widget render(String text, VoidCallback onPressed) {return ElevatedButton(style: ElevatedButton.styleFrom(shape: const RoundedRectangleBorder(),),onPressed: onPressed,child: Text(text),);}
}// 工廠方法 - 根據主題創建按鈕
class ButtonFactory {static AppButton createButton(ThemeType theme) {switch (theme) {case ThemeType.rounded:return RoundedButton();case ThemeType.square:return SquareButton();default:return RoundedButton();}}
}// 使用示例:
final button = ButtonFactory.createButton(currentTheme);
button.render('確認', () => print('Clicked'));
優勢:
- 將對象創建和使用分離
- 新增按鈕類型時只需擴展工廠,不修改客戶端代碼
- 統一創建接口
進階:抽象工廠模式 (Abstract Factory)
核心思想: 提供一個接口,用于創建相關或依賴對象的家族,而不需要指定具體類。
Flutter場景: 創建整套UI主題組件
// 抽象工廠 - 能生產全套UI組件
abstract class ThemeFactory {AppButton createButton();AppCard createCard();AppTextField createTextField();
}// 具體工廠1:生產經典主題組件
class ClassicThemeFactory implements ThemeFactory { AppButton createButton() => ClassicButton(); AppCard createCard() => ClassicCard(); AppTextField createTextField() => ClassicTextField();
}// 具體工廠2:生產清新主題組件
class FreshThemeFactory implements ThemeFactory { AppButton createButton() => FreshButton(); AppCard createCard() => FreshCard(); AppTextField createTextField() => FreshTextField();
}// 組件產品接口
abstract class AppButton {Widget render(String text);
}abstract class AppCard {Widget render(Widget child);
}abstract class AppTextField {Widget render(String hint);
}// 具體產品實現(以經典系列為例)
class ClassicButton implements AppButton { Widget render(String text) => ElevatedButton(style: ElevatedButton.styleFrom(primary: Colors.red),onPressed: () {},child: Text(text),);
}class ClassicCard implements AppCard { Widget render(Widget child) => Card(color: Colors.red[100],child: child,);
}class ClassicTextField implements AppTextField { Widget render(String hint) => TextField(decoration: InputDecoration(hintText: hint,border: const OutlineInputBorder(),),);
}// 清新系列產品實現類似...
使用抽象工廠:
class ThemeSwitcher extends StatelessWidget {final ThemeFactory factory;const ThemeSwitcher({required this.factory}); Widget build(BuildContext context) {return Column(children: [factory.createButton().render('提交'),const SizedBox(height: 20),factory.createCard().render(factory.createTextField().render('請輸入')),],);}
}// 在應用中使用
ThemeSwitcher(factory: ClassicThemeFactory()), // 經典主題
// 或
ThemeSwitcher(factory: FreshThemeFactory()), // 清新主題
優勢:
- 確保組件風格一致性(所有組件來自同一工廠)
- 切換主題只需更換工廠對象
- 新增主題系列不影響現有代碼
- 產品創建細節對客戶端隱藏
Flutter中的實際應用
- 主題管理系統
// 創建主題工廠
final factory = isDarkMode ? DarkThemeFactory() : LightThemeFactory();// 使用主題組件
return factory.createCard().render(Column(children: [factory.createTextField().render('用戶名'),factory.createButton().render('登錄'),],)
);
- 平臺適配組件
abstract class PlatformWidgetsFactory {AppBar createAppBar(String title);Button createButton(String text);
}class MaterialWidgetsFactory implements PlatformWidgetsFactory { AppBar createAppBar(String title) => AppBar(title: Text(title)); Button createButton(String text) => ElevatedButton(...);
}class CupertinoWidgetsFactory implements PlatformWidgetsFactory { AppBar createAppBar(String title) => CupertinoNavigationBar(middle: Text(title)); Button createButton(String text) => CupertinoButton(...);
}// 使用時
final factory = Platform.isIOS ? CupertinoWidgetsFactory() : MaterialWidgetsFactory();return Scaffold(appBar: factory.createAppBar('首頁'),body: factory.createButton('點擊我'),
);
- 復雜對話框構建
abstract class DialogFactory {Widget createTitle(String text);Widget createContent(String text);Widget createActions(List<ActionItem> items);
}class AlertDialogFactory implements DialogFactory { ... }
class BottomSheetDialogFactory implements DialogFactory { ... }
class FullscreenDialogFactory implements DialogFactory { ... }
工廠模式 vs 抽象工廠模式
特性 | 工廠方法模式 | 抽象工廠模式 |
---|---|---|
創建對象 | 單個產品 | 產品家族 |
主要目的 | 類延遲實例化到子類 | 創建相關對象組 |
擴展性 | 添加新產品需修改工廠 | 添加新系列只需新工廠 |
Flutter典型應用 | 條件創建單一組件 | 主題系統/平臺適配 |
最佳實踐指南
-
何時使用工廠方法:
- 需要創建單一類型對象
- 創建過程需要封裝
- 需要運行時決定對象類型
- 示例:根據用戶類型創建不同的個人主頁
-
何時使用抽象工廠:
- 需要創建多個相關對象
- 需要確保產品兼容性
- 需要支持多套產品系列
- 示例:主題系統、平臺適配、A/B測試UI方案
-
工廠模式優勢:
- ? 解耦創建和使用
- ? 符合開閉原則(擴展開放,修改關閉)
- ? 簡化復雜對象創建
- ? 提高代碼可測試性
-
需要注意:
- 避免過度設計簡單場景
- 工廠類可能成為"上帝對象"
- 新增產品類型可能需修改工廠接口
總結:工廠模式是你的UI流水線
- 工廠方法:你的"專屬定制工坊" - 根據需求生產特定類型產品
- 抽象工廠:你的"主題生產線" - 一鍵產出風格一致的全套產品
- 核心價值:創建邏輯和使用解耦,支持靈活擴展
- Flutter應用:主題系統、平臺適配、動態UI生成
💡 設計啟示: 當你發現代碼中有大量條件判斷創建不同對象時,就是工廠模式的用武之地!