想要动态创建不同风格的按钮?想一键切换整个主题?工厂模式就是你的"生产流水线"!
想象一下这个场景:
你决定扩大奶茶店业务,推出两个品牌系列:
- 经典系列:传统珍珠奶茶,红白配色
- 清新系列:水果茶,蓝绿配色
每个系列都有自己风格的:
- 杯子设计
- 吸管样式
- 包装袋
- 会员卡
问题来了: 当顾客点单时,你如何确保:
- 经典系列的奶茶配经典杯+经典吸管+经典包装?
- 清新系列的水果茶配清新杯+清新吸管+清新包装?
- 避免经典杯配清新吸管这种"混搭事故"?
解决方案:建立两个专属工厂:
- 经典工厂:专门生产经典杯、经典吸管、经典包装
- 清新工厂:专门生产清新杯、清新吸管、清新包装
当顾客选择系列后,你只需告诉对应的工厂:"给我一套装备!"工厂就会返回风格一致的全套产品。
在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生成
💡 设计启示: 当你发现代码中有大量条件判断创建不同对象时,就是工厂模式的用武之地!