Python设计模式深度解析:建造者模式(Builder Pattern)完全指南

    • 前言
    • 什么是建造者模式?
      • 建造者模式的核心思想
      • 模式的核心组成
    • 实际案例一:UI选择组件的动态构建
      • 抽象建造者基类
      • 具体建造者实现
        • 列表框建造者
        • 复选框建造者
      • 工厂建造者(Director角色)
      • 完整的应用构建
    • 实际案例二:数据结构的分步构建
      • 州数据的构建
    • 高级建造者模式:流式接口
    • 建造者模式的优缺点
      • 优点
      • 缺点
    • 与其他模式的区别
      • 建造者模式 vs 工厂模式
      • 建造者模式 vs 抽象工厂模式
    • 实际应用场景
    • 最佳实践
    • 总结

前言

在软件开发中,我们经常需要创建复杂的对象,这些对象可能包含多个组成部分,并且创建过程可能很复杂。如果直接在构造函数中处理所有的创建逻辑,会导致代码难以维护和扩展。建造者模式(Builder Pattern)正是为了解决这个问题而诞生的一种创建型设计模式。

本文将通过实际的UI构建和数据处理案例,深入讲解Python中建造者模式的实现原理、应用场景和最佳实践。

什么是建造者模式?

建造者模式是一种创建型设计模式,它允许你分步骤创建复杂对象。该模式将复杂对象的构建过程分解为多个简单的步骤,通过不同的建造者可以创建不同表示的对象。

建造者模式的核心思想

将对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。

模式的核心组成

  1. Director(指挥者):控制构建过程,调用建造者的方法
  2. Builder(抽象建造者):定义构建复杂对象的抽象接口
  3. ConcreteBuilder(具体建造者):实现Builder接口,构建具体产品
  4. Product(产品):被构建的复杂对象

实际案例一:UI选择组件的动态构建

让我们通过一个实际的UI构建案例来理解建造者模式。这个案例展示了如何根据数据量的不同,动态选择不同的UI组件。

抽象建造者基类

class MultiChoice:"""多选组件的抽象基类"""def __init__(self, frame, choiceList):self.choices = choiceList    # 保存选择列表self.frame = frame# 待派生类实现的抽象方法def makeUI(self): pass  # 构建UI组件def getSelected(self): pass  # 获取选中项目def clearAll(self):"""清除框架中的所有组件"""for widget in self.frame.winfo_children():widget.destroy()

具体建造者实现

列表框建造者
class ListboxChoice(MultiChoice):"""列表框选择建造者"""def __init__(self, frame, choices):super().__init__(frame, choices)def makeUI(self):"""构建列表框UI"""self.clearAll()# 创建多选列表框self.list = Listbox(self.frame, selectmode=MULTIPLE)self.list.pack()# 添加选项到列表框for item in self.choices:self.list.insert(END, item)def getSelected(self):"""获取选中的项目"""sel = self.list.curselection()selected_items = []for i in sel:item = self.list.get(i)selected_items.append(item)return selected_items
复选框建造者
class Checkbox(Checkbutton):"""自定义复选框组件"""def __init__(self, root, text, var):super().__init__(root, text=text, variable=var)self.text = textself.var = vardef getText(self):return self.textdef getVar(self):return int(self.var.get())class CheckboxChoice(MultiChoice):"""复选框选择建造者"""def __init__(self, panel, choices):super().__init__(panel, choices)def makeUI(self):"""构建复选框UI"""self.boxes = []  # 存储复选框列表self.clearAll()row = 0for name in self.choices:var = IntVar()  # 创建变量checkbox = Checkbox(self.frame, name, var)self.boxes.append(checkbox)checkbox.grid(column=0, row=row, sticky=W)row += 1def getSelected(self):"""获取选中的复选框"""selected_items = []for box in self.boxes:if box.getVar() > 0:selected_items.append(box.getText())return selected_items

工厂建造者(Director角色)

class ChoiceFactory:"""选择组件工厂 - 充当Director角色"""def getChoiceUI(self, choices, frame):"""根据选择数量决定使用哪种UI组件"""if len(choices) <= 3:# 选项少时使用复选框return CheckboxChoice(frame, choices)else:# 选项多时使用列表框return ListboxChoice(frame, choices)

完整的应用构建

import tkinter as tk
from tkinter import *
from tkinter import messageboxclass Securities:"""证券数据类"""def __init__(self, name, security_list):self.name = nameself.list = security_listdef getName(self):return self.namedef getList(self):return self.listclass BuildUI:"""UI构建器类 - 主要的Director"""def __init__(self, root):self.root = rootself.root.geometry("400x300")self.root.title("投资组合构建器")self.seclist = []def build(self):"""构建完整的应用界面"""# 第一步:创建数据self._build_data()# 第二步:构建左侧选择面板self._build_left_panel()# 第三步:构建右侧显示面板self._build_right_panel()# 第四步:构建控制按钮self._build_controls()def _build_data(self):"""构建证券数据"""self.stocks = Securities("股票", ["苹果公司", "微软", "谷歌", "亚马逊", "特斯拉"])self.seclist.append(self.stocks)self.bonds = Securities("债券", ["国债2024", "企业债2025", "地方债2026"])self.seclist.append(self.bonds)self.funds = Securities("基金", ["沪深300ETF", "创业板ETF"])self.seclist.append(self.funds)def _build_left_panel(self):"""构建左侧选择面板"""left_frame = Frame(self.root)left_frame.grid(row=0, column=0, padx=10, pady=10)Label(left_frame, text="投资类型:").pack()self.leftList = Listbox(left_frame, exportselection=FALSE)self.leftList.pack()# 添加证券类型for sec in self.seclist:self.leftList.insert(END, sec.getName())# 绑定选择事件self.leftList.bind('<<ListboxSelect>>', self.on_type_select)def _build_right_panel(self):"""构建右侧显示面板"""self.right_frame = Frame(self.root, name="right")self.right_frame.grid(row=0, column=1, padx=10, pady=10)Label(self.right_frame, text="具体选择:").pack()def _build_controls(self):"""构建控制按钮"""button_frame = Frame(self.root)button_frame.grid(row=1, column=0, columnspan=2, pady=10)show_button = Button(button_frame, text="显示选择", command=self.show_selected)show_button.pack()def on_type_select(self, event):"""类型选择事件处理"""selection = self.leftList.curselection()if selection:index = int(selection[0])securities = self.seclist[index]# 使用工厂创建合适的UI组件factory = ChoiceFactory()self.choice_ui = factory.getChoiceUI(securities.getList(), self.right_frame)self.choice_ui.makeUI()def show_selected(self):"""显示选中的项目"""if hasattr(self, 'choice_ui'):selected = self.choice_ui.getSelected()if selected:message = "您选择了:\n" + "\n".join(selected)messagebox.showinfo("选择结果", message)else:messagebox.showinfo("提示", "请先选择投资产品")# 使用示例
def main():root = tk.Tk()builder = BuildUI(root)builder.build()root.mainloop()if __name__ == "__main__":main()

实际案例二:数据结构的分步构建

让我们看另一个案例,展示如何使用建造者模式构建复杂的数据结构:

州数据的构建

class State:"""州数据对象"""def __init__(self, state_string):self._tokens = state_string.strip().split(",")self._statename = ""if len(self._tokens) > 3:self._statename = self._tokens[0]self._abbrev = self._tokens[1]self._founded = self._tokens[2]self._capital = self._tokens[3]def getStateName(self):return self._statenamedef getCapital(self):return self._capitaldef getAbbrev(self):return self._abbrevdef getFounded(self):return self._foundedclass StateListBuilder:"""州列表建造者"""def __init__(self):self._states = []def load_from_file(self, filename):"""从文件加载数据"""try:with open(filename, 'r', encoding='utf-8') as file:self.contents = file.readlines()except FileNotFoundError:# 如果文件不存在,使用示例数据self.contents = ["California,CA,1850,Sacramento\n","Texas,TX,1845,Austin\n","New York,NY,1788,Albany\n","Florida,FL,1845,Tallahassee\n"]return selfdef parse_states(self):"""解析州数据"""for line in self.contents:if len(line.strip()) > 0:state = State(line)if state.getStateName():  # 确保解析成功self._states.append(state)return selfdef sort_by_name(self):"""按名称排序"""self._states.sort(key=lambda s: s.getStateName())return selfdef filter_by_founded_year(self, min_year):"""按成立年份过滤"""filtered_states = []for state in self._states:try:if int(state.getFounded()) >= min_year:filtered_states.append(state)except ValueError:# 如果年份格式不正确,保留该州filtered_states.append(state)self._states = filtered_statesreturn selfdef build(self):"""构建最终的州列表"""return self._states# 使用建造者模式构建州列表
def create_state_list():"""演示建造者模式的使用"""# 方式1:基本构建basic_states = (StateListBuilder().load_from_file("states.txt").parse_states().build())# 方式2:带排序的构建sorted_states = (StateListBuilder().load_from_file("states.txt").parse_states().sort_by_name().build())# 方式3:带过滤的构建modern_states = (StateListBuilder().load_from_file("states.txt").parse_states().filter_by_founded_year(1800).sort_by_name().build())return basic_states, sorted_states, modern_states

高级建造者模式:流式接口

流式建造者模式提供了更优雅的API:

class ComputerBuilder:"""计算机建造者 - 流式接口"""def __init__(self):self.computer = {'cpu': None,'memory': None,'storage': None,'graphics': None,'peripherals': []}def cpu(self, cpu_type):"""设置CPU"""self.computer['cpu'] = cpu_typereturn selfdef memory(self, memory_size):"""设置内存"""self.computer['memory'] = memory_sizereturn selfdef storage(self, storage_type):"""设置存储"""self.computer['storage'] = storage_typereturn selfdef graphics(self, graphics_card):"""设置显卡"""self.computer['graphics'] = graphics_cardreturn selfdef add_peripheral(self, peripheral):"""添加外设"""self.computer['peripherals'].append(peripheral)return selfdef build(self):"""构建最终的计算机配置"""return self.computer.copy()# 使用流式建造者
def demo_fluent_builder():"""演示流式建造者的使用"""# 游戏电脑配置gaming_pc = (ComputerBuilder().cpu("Intel i9-12900K").memory("32GB DDR4").storage("1TB NVMe SSD").graphics("RTX 4080").add_peripheral("机械键盘").add_peripheral("游戏鼠标").add_peripheral("144Hz显示器").build())# 办公电脑配置office_pc = (ComputerBuilder().cpu("Intel i5-12400").memory("16GB DDR4").storage("512GB SSD").graphics("集成显卡").add_peripheral("无线键鼠套装").build())print("游戏电脑配置:", gaming_pc)print("办公电脑配置:", office_pc)if __name__ == "__main__":demo_fluent_builder()

建造者模式的优缺点

优点

  1. 分离构建和表示:构建过程和最终表示分离,提高了灵活性
  2. 精细控制构建过程:可以精细控制对象的构建过程
  3. 代码复用:相同的构建过程可以创建不同的产品
  4. 易于扩展:可以独立地扩展建造者和产品
  5. 支持流式接口:提供更优雅的API

缺点

  1. 增加代码复杂性:需要创建多个新类
  2. 产品相似性要求:要求产品有足够的相似性
  3. 内部结构暴露:建造者需要了解产品的内部结构

与其他模式的区别

建造者模式 vs 工厂模式

特性工厂模式建造者模式
目的创建对象构建复杂对象
过程一步创建分步构建
复杂度简单对象复杂对象
控制工厂控制指挥者控制
产品单一产品复杂产品

建造者模式 vs 抽象工厂模式

  • 抽象工厂模式:强调产品族的创建
  • 建造者模式:强调复杂对象的分步构建

实际应用场景

  1. SQL查询构建:分步构建复杂的SQL语句
  2. 配置对象创建:构建复杂的配置对象
  3. UI组件构建:构建复杂的用户界面组件
  4. 文档生成:分步构建复杂的文档结构
  5. 测试数据构建:构建复杂的测试数据对象

最佳实践

  1. 明确构建步骤:将复杂的构建过程分解为清晰的步骤
  2. 使用流式接口:提供更优雅的API体验
  3. 验证构建结果:在build()方法中验证对象的完整性
  4. 支持重置:允许重置建造者以构建新对象
  5. 文档化构建过程:清楚地文档化每个构建步骤的作用

总结

建造者模式是一种强大的创建型设计模式,它通过将复杂对象的构建过程分解为多个简单步骤,提供了灵活且可控的对象创建方式。

通过本文的学习,我们了解了:

  • 建造者模式的核心概念和组成
  • 实际的UI构建和数据处理应用案例
  • 流式建造者的优雅实现
  • 与其他创建型模式的区别
  • 实际应用场景和最佳实践

在实际开发中,当你需要创建复杂对象,并且希望构建过程具有良好的可控性和可扩展性时,建造者模式是一个很好的选择。记住,设计模式是工具,选择最适合当前问题的解决方案才是最重要的。

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

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

相关文章

elementuiPlus+vue3手脚架后台管理系统,上生产环境之后,如何隐藏vite.config.ts的target地址

在项目根目录创建 .env.production 文件&#xff1a; VITE_API_TARGEThttps://your-real-api.com修改 vite.config.ts&#xff1a; import { defineConfig, loadEnv } from viteexport default defineConfig(({ mode }) > {const env loadEnv(mode, process.cwd(), )return…

ARCGIS PRO DSK 颜色选择控件(ColorPickerControl)的调用

颜色选择控件ColorPickerControl 。一、XAML 集成方式 1 、在WPF窗体上使用&#xff0c;xml&#xff1a;加入空间命名引用xmlns:ui1"clr-namespace:ArcGIS.Desktop.Internal.Mapping.Symbology;assemblyArcGIS.Desktop.Mapping" xmlns:uil"http://schemas.xceed…

深浅拷贝以及函数缓存

目录 数据类型介绍 基本数据类型&#xff08;Primitive Types&#xff09; 引用数据类型&#xff08;Reference Types&#xff09; 浅拷贝 深拷贝 利用JSON的序列化和反序列化实现深拷贝 递归实现深拷贝 第三方库lodash的cloneDeep 函数缓存的概念 实现方法 数据类型介…

第六届信号处理与计算机科学国际学术会议(SPCS 2025)

重要信息 官网&#xff1a;www.icspcs.org &#xff08;详情见官网&#xff09; 时间&#xff1a;2025年8月15-17日 地点&#xff1a;西安 主题 信号处理与智能计算计算科学与人工智能网络与多媒体技术数字信号处理 雷达信号处理 通信信号处理 临时和传感器网络 模拟和…

MongoDB:一个灵活的、可扩展的 NoSQL 数据库

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

系统思考场景应用

最近一直在与不同行业头部企业共同探讨系统思考这个主题。一些新的合作伙伴也常常问我&#xff0c;系统思考究竟能为客户解决什么痛点&#xff1f; 这两天上课客户的核心需求是&#xff1a;全局思维。在过去的几年里&#xff0c;我深切体会到&#xff0c;随着外部环境的快速变化…

SQL预编译:安全高效数据库操作的关键

通过占位符&#xff08;如 ? 或命名参数&#xff09;编写预编译的 SQL 语句&#xff08;通常通过 PreparedStatement 实现&#xff09;是数据库操作的最佳实践&#xff0c;主要好处包括&#xff1a;&#x1f512; 1. 防止 SQL 注入攻击&#xff08;核心安全优势&#xff09; 问…

springboot实验室管理系统-计算机毕业设计源码20916

摘 要 随着高校实验室管理需求的不断增加&#xff0c;传统的管理方式已经难以满足现代教育的要求。为了解决这一问题&#xff0c;本文设计并实现了一种基于VUE和SpringBoot的实验室管理系统。该系统采用前后端分离的架构&#xff0c;前端使用VUE框架&#xff0c;后端基于Sprin…

spdringboot共享学习室小程序 计算机毕业设计源码27728

摘 要 共享学习室小程序是一款基于SpringBoot框架开发的移动端应用&#xff0c;旨在提供一个便捷的自习室预约、管理和资源共享平台。通过该小程序&#xff0c;用户可以方便地预约自习室、查看资讯、提交反馈意见&#xff0c;同时进行失物招领、查看订单信息等多项操作。对于管…

JVM——JVM 的内存区域是如何划分的?

Java 虚拟机运行时数据区分为方法区、堆、虚拟机栈、本地方法栈、程序计数器。 方法区(Method Area): [1] 存储类信息、常量、静态变量和即时编译器(JIT)编译后的代码。 [2] 属于线程共享区域&#xff0c;所有线程共享方法区内存 [3] 在 JDK8之前&#xff0c;HotSpot使用永久代…

SpringAi笔记

简介 :: Spring AI 中文文档 Spring AI 解决了 AI 集成的根本难题&#xff1a;将企业数据和 API 与 AI 模型连接起来。 聊天客户端 API (ChatClient ) 发起对模型的调用和响应 创建&#xff1a;其中可以通过bean来注入创建好的chatClient 可以使用Qualifier注解&#xff0c;…

基于SD-WAN的智慧高速解决方案:高效、低成本的智能交通实践

随着交通网络的智能化需求逐渐增加&#xff0c;智慧高速建设已成为提升通行效率、优化安全性、实现交通现代化管理的重要方向。在本文中&#xff0c;我们将以某智慧高速项目为例&#xff0c;详细探讨如何通过 SD-WAN 技术与多种智能化手段结合&#xff0c;实现“低成本、高效率…

Towards Low Light Enhancement with RAW Images 论文阅读

利用 RAW 图像实现低光增强 摘要 在本文中&#xff0c;我们首次进行了基准研究&#xff0c;详细阐述了在低光增强中使用 RAW 图像的优越性&#xff0c;并提出了一种新颖的替代方案&#xff0c;以更灵活和实用的方式利用 RAW 图像。受对典型图像处理流程的全面考虑启发&#xff…

smolagents - 如何在mac用agents做简单算术题

smolagent是hf推出的agent开发库&#xff0c;简洁易用。这里尝试用smolagents完成简单数学题目。 1 smolagents安装 conda create -n smolagents python3.12 conda activate smolagents pip install smolagents pip install smolagents[mlx-lm] 由于是在mac使用mlx&#xff0c;…

【无标题】LighthouseGS:面向全景式移动拍摄的室内结构感知三维高斯泼溅

标题&#xff1a;<LighthouseGS: Indoor Structure-aware 3D Gaussian Splatting for Panorama-Style Mobile Captures> 论文&#xff1a;https://arxiv.org/pdf/2507.06109 来源&#xff1a;南京大学&#xff1b;复旦大学&#xff1b;华为诺亚实验室 文章目录摘要一、前…

el-table中type=“selection“选中数据如何回显

效果如下代码如下 关键函数&#xff1a;toggleRowSelection(this.tableData[i])设置默认选中数据。 <template><el-tableref"multipleTable":data"tableData"tooltip-effect"dark"style"width: 100%"selection-change"h…

为来时路,OCM拿证学习和考试

为何选择OCM&#xff1f;OCM的含金量无需多言。全球持证人数不足万人&#xff0c;中国地区更是寥寥千人。它不仅是技术实力的象征&#xff0c;更是通往金融、互联网、通信等核心企业高薪岗位的“通行证”。据行业数据显示&#xff0c;持有OCM认证的技术人员&#xff0c;薪资普遍…

beautiful-react-hooks库——入门实践常用hook详解

简介 beautiful-react-hooks 是一个专为 React 设计的高质量自定义 Hooks 集合&#xff0c;涵盖了事件、状态、生命周期、DOM 操作、性能优化等多个方面&#xff0c;极大提升了函数组件的开发效率和代码复用性。 安装方法 npm install beautiful-react-hooks # 或 yarn add …

DOM 规范中的 MutationObserver 接口

MutationObserver 接口DOM规范中的 MutationObserver 接口可以在DOM被修改时异步执行回调。使用MutationObserver可以观察整个文档、DOM树的一部分或某个元素&#xff0c;元素属性、字节点、文本等。新引进的MutationObserver接口取代了已废弃的MutationEvent。MutationObserve…

3.7 小结

图3-7-1点云可视化点云可视化工具就像是打开点云数据宝藏大门的钥匙&#xff0c;能让我们直观地理解和分析这些复杂的数据。本章节&#xff0c;主要介绍了PCL、Open3D、Matplotlib、PCShow、VTK 这几种点云可视化工具。PCL&#xff08;Point Cloud Library&#xff09;是专注于…