建造者模式 - Flutter中的乐高大师,优雅组装复杂UI组件!

痛点场景:复杂的对话框配置

假设你需要创建一个多功能对话框:

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)
  • 🌋 相似组件创建需要重复代码

建造者模式解决方案

核心思想: 将复杂对象的构建与其表示分离,使同样的构建过程可以创建不同的表示。

四个关键角色:

  1. 产品(Product): 最终要构建的复杂对象(如对话框)
  2. 抽象建造者(Builder): 定义构建步骤的接口
  3. 具体建造者(ConcreteBuilder): 实现构建步骤
  4. 指挥者(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()

建造者模式最佳实践

  1. 何时使用建造者模式:

    • 对象需要多个步骤或复杂配置才能创建
    • 构造函数参数超过4个
    • 需要创建不可变对象但又要灵活配置
    • 相同构建过程需要创建不同表示
  2. 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;
    }
    
  3. 性能优化:

    // 使用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个或创建逻辑复杂时,建造者模式能显著改善代码质量!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86932.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86932.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+Spring Boot的大学校园生活信息平台

源码编号&#xff1a;S559 源码名称&#xff1a;基于Spring Boot的大学校园生活信息平台 用户类型&#xff1a;双角色&#xff0c;用户、管理员 数据库表数量&#xff1a;17 张表 主要技术&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven 运行环境&#xff1a;Wind…

C# .NET Framework 中的高效 MQTT 消息传递

介绍&#xff1a; 在当今互联互通的世界里&#xff0c;设备之间高效可靠的通信至关重要。MQTT&#xff08;消息队列遥测传输&#xff09;就是为此而设计的轻量级消息传递协议。本文将探讨 MQTT 是什么、它的优势以及如何在 .NET 框架中设置和实现它。最后&#xff0c;您将对 M…

nn.Embedding 和 word2vec 的区别

理解它们的关键在于​​区分概念层级和职责​​。 可以将它们类比为&#xff1a; ​​word2vec&#xff1a;​​ 一个​​专门制作高质量词向量模型的“工厂”​​。​​nn.Embedding&#xff1a;​​ 一个​​可存储、查找并训练词向量的“智能储物柜”​​&#xff08;作为…

华为云Flexus+DeepSeek征文|​​华为云ModelArts Studio大模型 + WPS:AI智能PPT生成解决方案​

引言&#xff1a;告别繁琐PPT制作&#xff0c;AI赋能高效办公 ​​ 在商业汇报、学术研究、产品发布等场景中&#xff0c;制作专业PPT往往需要耗费大量时间进行内容整理、逻辑梳理和视觉美化。​​华为云ModelArts Studio大模型​​与​​WPS​​深度结合&#xff0c;推出AI-P…

【连接redis超时】

报错 客户端输出缓冲区超限 Client … scheduled to be closed ASAP for overcoming of output buffer limits 表示这些客户端&#xff08;通过 psubscribe 命令进行发布订阅操作&#xff09;的输出缓冲区超过了 Redis 配置的限制&#xff0c;Redis 会关闭这些客户端连接来避免…

PHP「Not enough Memory」实战排错笔记

目录 PHP「Not enough Memory」实战排错笔记 1. 背景 2. 快速定位 3. 为什么 5 MB 的图片能耗尽 128 MB&#xff1f; 3.1 粗略估算公式&#xff08;GD&#xff09; 4. 实际峰值监控 5. 解决过程 6. 最佳实践与防御措施 7. 总结 PHP「Not enough Memory」实战排错笔记 —…

Java垃圾回收机制和三色标记算法

一、对象内存回收 对于对象回收&#xff0c;需要先判断垃圾对象&#xff0c;然后收集垃圾。 收集垃圾采用垃圾收集算法和垃圾收集器。 判断垃圾对象&#xff0c;通常采用可达性分析算法。 引用计数法 每个对象设置一个引用计数器。每被引用一次&#xff0c;计数器就加1&am…

基于python网络数据挖掘的二手房推荐系统

基于网络数据挖掘的二手房推荐系统设计与实现 【摘要】 随着互联网技术在房地产行业的深入应用&#xff0c;线上房源信息呈爆炸式增长&#xff0c;给购房者带来了信息过载的挑战。为了提升二手房筛选的效率与精准度&#xff0c;本文设计并实现了一个基于网络数据挖掘的二手房推…

Java + 阿里云 Gmsse 实现 SSL 国密通信

前言 解决接口或页面仅密信浏览器&#xff08;或 360 国密浏览器&#xff09;能访问的问题 测试页面 测试网站-中国银行&#xff1a;https://ebssec.boc.cn/boc15/help.html 使用其他浏览器&#xff08;google&#xff0c;edge等&#xff09;打开 使用密信浏览器打开 解决…

国产数据库分类总结

文章目录 一、华为系数据库1. 华为 GaussDB 二、阿里系数据库1. 阿里云 OceanBase2. PolarDB&#xff08;阿里云自研&#xff09; 三、腾讯系数据库1. TDSQL&#xff08;腾讯云&#xff09;2. TBase&#xff08;PostgreSQL增强版&#xff09; 四、传统国产数据库1. 达梦数据库&…

解密闭包:函数如何记住外部变量

&#x1f9e0; 什么是闭包&#xff1f; 闭包是一个函数对象&#xff0c;它不仅记住它的代码逻辑&#xff0c;还记住了定义它时的自由变量&#xff08;即非全局也非局部&#xff0c;但被内部函数引用的变量&#xff09;。即使外部函数已经执行完毕&#xff0c;这些自由变量的值…

I2C协议详解及STM32 HAL库硬件I2C卡死问题分析

一、I2C协议详解 1. I2C协议概述 Inter-Integrated Circuit (I2C) 是由 Philips 半导体&#xff08;现 NXP 半导体&#xff09;于 1980 年代设计的一种同步串行通信总线协议。该协议采用半双工通信模式&#xff0c;支持多主从架构&#xff0c;专为短距离、低速率的芯片间通信…

HTTP协议-后端接收请求

起因就是不知道post这个请求体中这些格式有什么区别&#xff0c;后端又怎么去接收这些不同格式的内容 Get请求 get请求是比较简单的一类 正常的直接用参数接收&#xff08;不写的话名字要匹配&#xff09;或者RequestParam都可以接收&#xff0c;用对象绑定也可以 resultful…

HTML5 实现的圣诞主题网站源码,使用了 HTML5 和 CSS3 技术,界面美观、节日氛围浓厚。

以下是一个 HTML5 实现的圣诞主题网站源码&#xff0c;使用了 HTML5 和 CSS3 技术&#xff0c;界面美观、节日氛围浓厚。它包括&#xff1a; 圣诞树动画 &#x1f384;雪花飘落特效 ❄️圣诞祝福语 &#x1f381;响应式布局&#xff0c;适配移动端 你可以将代码保存为 index.…

Spring Cloud Bus 和 Spring Cloud Stream

Spring Cloud Bus 和 Spring Cloud Stream 都是 Spring Cloud 生态中的消息通信组件&#xff0c;但它们的定位和使用场景有显著区别&#xff1a; 1. Spring Cloud Bus 核心定位&#xff1a;分布式系统的消息广播&#xff08;配置刷新、事件传播&#xff09;。 典型场景&#x…

磁悬浮轴承位移信号的高精度估计:卡尔曼滤波算法深度解析

无需位移传感器,滤波算法如何实现微米级精度? 磁悬浮轴承作为革命性的非接触式支承技术,凭借无磨损、无需润滑、高转速等优势,在飞轮储能、高速电机、人工心脏泵和航空航天领域获得了广泛应用。其核心控制依赖于对转子位移信号的高精度实时检测,传统电涡流传感器虽能提供位…

DAY 43 预训练模型

目录 一、预训练的概念 二、 经典的预训练模型 2.1 CNN架构预训练模型 2.2 Transformer类预训练模型 2.3 自监督预训练模型 三、常见的分类预训练模型介绍 3.1 预训练模型的发展史 3.2 预训练模型的训练策略 知识点回顾&#xff1a; 预训练的概念常见的分类预训练模型图像…

Redis:事物

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Redis &#x1f525; 什么是事务 Redis的事务和MySQL的事务概念上是类似的.都是把⼀系列操作绑定成⼀组.让这⼀组能够批量执⾏. 但是注意体会Redis的事务和MySQL事务的区别: 弱化的原⼦性:redi…

CppCon 2018 学习:An allocator is a handle to a heap Lessons learned from std::pmr

“An allocator is a handle to a heap — Lessons learned from std::pmr” 翻译过来就是&#xff1a;“分配器&#xff08;allocator&#xff09;是对堆&#xff08;heap&#xff09;的一种句柄&#xff08;handle&#xff09;——从 std::pmr 中学到的经验”。 基础概念 分…

设备健康实时监测方法演进:从传感网络到AI决策树的工业智能实践

引言&#xff1a;当设备运维遇上AIoT革命 在工业4.0进程中&#xff0c;​毫秒级设备状态捕获能力正成为智能工厂的核心竞争力。传统监测方法因数据滞后、诊断粗放被诟病&#xff0c;本文将深入探讨三大前沿实时监测技术路径&#xff0c;并揭秘中讯烛龙系统如何通过深度强化学习…