痛點場景:復雜的對話框配置
假設你需要創建一個多功能對話框:
CustomDialog(title: '警告',content: '確定要刪除嗎?',titleStyle: TextStyle(fontSize: 20, color: Colors.red),contentStyle: TextStyle(fontSize: 16),backgroundColor: Colors.grey[200],barrierDismissible: false,positiveButton: DialogButton(text: '確認',color: Colors.red,onPressed: () => print('Confirmed'),),negativeButton: DialogButton(text: '取消',color: Colors.grey,onPressed: () => print('Cancelled'),),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10),),// 還有10個參數...
)
問題爆發點:
- 🚨 構造函數參數爆炸(難以維護和使用)
- 💥 必須記住參數順序
- 🔥 可選參數處理困難(需要傳入大量null)
- 🌋 相似組件創建需要重復代碼
建造者模式解決方案
核心思想: 將復雜對象的構建與其表示分離,使同樣的構建過程可以創建不同的表示。
四個關鍵角色:
- 產品(Product): 最終要構建的復雜對象(如對話框)
- 抽象建造者(Builder): 定義構建步驟的接口
- 具體建造者(ConcreteBuilder): 實現構建步驟
- 指揮者(Director): 控制構建過程(Flutter中常可省略)
Flutter對話框建造者實現
1. 定義產品類
class DialogConfig {String? title;String? content;TextStyle? titleStyle;TextStyle? contentStyle;Color? backgroundColor;bool barrierDismissible = true;DialogButton? positiveButton;DialogButton? negativeButton;ShapeBorder? shape;// 其他配置項...
}class DialogButton {final String text;final Color color;final VoidCallback onPressed;DialogButton({required this.text,required this.color,required this.onPressed,});
}
2. 創建建造者類
class DialogBuilder {final DialogConfig _config = DialogConfig();// 設置標題DialogBuilder title(String title, {TextStyle? style}) {_config.title = title;_config.titleStyle = style;return this;}// 設置內容DialogBuilder content(String content, {TextStyle? style}) {_config.content = content;_config.contentStyle = style;return this;}// 設置背景DialogBuilder backgroundColor(Color color) {_config.backgroundColor = color;return this;}// 添加確認按鈕DialogBuilder withPositiveButton(String text, {required VoidCallback onPressed,Color color = Colors.blue,}) {_config.positiveButton = DialogButton(text: text,color: color,onPressed: onPressed,);return this;}// 構建最終產品Widget build() {return AlertDialog(title: _config.title != null ? Text(_config.title!, style: _config.titleStyle): null,content: _config.content != null? Text(_config.content!, style: _config.contentStyle): null,backgroundColor: _config.backgroundColor,actions: [if (_config.negativeButton != null)TextButton(style: TextButton.styleFrom(foregroundColor: _config.negativeButton!.color,),onPressed: _config.negativeButton!.onPressed,child: Text(_config.negativeButton!.text),),if (_config.positiveButton != null)TextButton(style: TextButton.styleFrom(foregroundColor: _config.positiveButton!.color,),onPressed: _config.positiveButton!.onPressed,child: Text(_config.positiveButton!.text),),],shape: _config.shape,);}
}
3. 在Flutter中使用
// 基礎用法
showDialog(context: context,builder: (_) => DialogBuilder().title('警告', style: TextStyle(color: Colors.red)).content('確定要刪除這個文件嗎?').withPositiveButton('刪除', onPressed: () => Navigator.pop(context)).build()
);// 復雜用法
final deleteDialog = DialogBuilder().title('永久刪除', style: TextStyle(fontWeight: FontWeight.bold)).content('此操作將永久刪除數據,不可恢復!').backgroundColor(Colors.grey[100]!).withPositiveButton('確認刪除', onPressed: () => _deleteItem(),color: Colors.red,).withNegativeButton('取消').build();showDialog(context: context, builder: (_) => deleteDialog);
Flutter框架中的建造者模式
實際上,Flutter自身大量使用了建造者模式的變體:
1. TextStyle
的copyWith方法
TextStyle style = TextStyle(fontSize: 16,color: Colors.black,
).copyWith(fontWeight: FontWeight.bold,decoration: TextDecoration.underline,
);
2. ThemeData
的構造方式
final theme = ThemeData.light().copyWith(primaryColor: Colors.blue,buttonTheme: ButtonThemeData(buttonColor: Colors.blue[700],),
);
3. BoxDecoration
的鏈式配置
BoxDecoration(color: Colors.blue,borderRadius: BorderRadius.circular(10),boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 6),],
)
高級應用:響應式布局建造者
創建一個能自動適應不同屏幕尺寸的布局建造者:
class ResponsiveBuilder {final List<Widget> _children = [];double _spacing = 16.0;Axis _direction = Axis.vertical;int _crossAxisCount = 2;ResponsiveBuilder addChild(Widget child) {_children.add(child);return this;}ResponsiveBuilder spacing(double value) {_spacing = value;return this;}ResponsiveBuilder horizontal() {_direction = Axis.horizontal;return this;}ResponsiveBuilder columns(int count) {_crossAxisCount = count;return this;}Widget build() {return LayoutBuilder(builder: (context, constraints) {if (constraints.maxWidth > 600) {return GridView.count(crossAxisCount: _crossAxisCount,childAspectRatio: 1.0,mainAxisSpacing: _spacing,crossAxisSpacing: _spacing,children: _children,);} else {return ListView.separated(scrollDirection: _direction,itemCount: _children.length,separatorBuilder: (_, __) => SizedBox(width: _direction == Axis.horizontal ? _spacing : 0,height: _direction == Axis.vertical ? _spacing : 0,),itemBuilder: (context, index) => _children[index],);}},);}
}// 使用示例
ResponsiveBuilder().addChild(ProductCard(product1)).addChild(ProductCard(product2)).spacing(20).columns(3).build()
建造者模式最佳實踐
-
何時使用建造者模式:
- 對象需要多個步驟或復雜配置才能創建
- 構造函數參數超過4個
- 需要創建不可變對象但又要靈活配置
- 相同構建過程需要創建不同表示
-
Flutter特化技巧:
// 使用可選命名參數簡化初始創建 DialogBuilder({String? title, String? content}) {if (title != null) _config.title = title;if (content != null) _config.content = content; }// 添加預置配置 DialogBuilder.error() {return DialogBuilder().titleColor(Colors.red).backgroundColor(Colors.red[50]!); }// 支持運算符重載 DialogBuilder operator <<(Widget child) {addChild(child);return this; }
-
性能優化:
// 使用memoization緩存常用配置 class DialogBuilder {static final Map<String, DialogConfig> _presets = {};static DialogBuilder preset(String name) {if (!_presets.containsKey(name)) {_presets[name] = _createPreset(name);}return DialogBuilder.fromConfig(_presets[name]!);} }
建造者模式 vs 工廠模式
特性 | 建造者模式 | 工廠模式 |
---|---|---|
主要目的 | 分步構建復雜對象 | 創建對象家族 |
構建過程 | 顯式控制每個步驟 | 隱藏創建細節 |
適用場景 | 包含多個組件的對象 | 不同系列的對象 |
Flutter應用 | 復雜組件配置、響應式布局 | 主題系統、平臺適配 |
建造者模式的強大變體
1. 階段式建造者
abstract class DialogBuilderPhase1 {DialogBuilderPhase2 setTitle(String title);
}abstract class DialogBuilderPhase2 {DialogBuilderPhase3 setContent(String content);
}class DialogBuilder implements DialogBuilderPhase1, DialogBuilderPhase2 {// 分階段實現...
}// 強制按順序調用:
DialogBuilder().setTitle('標題') // 必須第一步.setContent('內容') // 必須第二步.build();
2. 裝飾器增強建造者
class DialogDecorator implements DialogBuilder {final DialogBuilder _builder;DialogDecorator(this._builder); DialogBuilder title(String title) {_builder.title(title);return this;}// 添加額外功能DialogDecorator withAnimation(Duration duration) {// 添加動畫邏輯return this;}
}// 使用增強功能
DialogDecorator(CustomDialogBuilder()).title('動畫對話框').withAnimation(Duration(seconds: 1)).build();
總結:建造者模式是你的UI組裝線
- 核心價值: 將復雜對象的構建過程分解為可管理的步驟
- Flutter優勢:
- 解決"參數爆炸"問題
- 創建不可變對象的靈活方式
- 提高大型組件配置的可讀性
- 支持流暢的鏈式調用
- 適用場景: 復雜對話框、表單構建、響應式布局、主題配置
🔧 設計啟示: 當組件參數超過5個或創建邏輯復雜時,建造者模式能顯著改善代碼質量!