【设计模式】Python 设计模式之建造者模式(Builder Pattern)详解
Python 设计模式之建造者模式(Builder Pattern)详解
在软件开发中,创建复杂对象往往需要多个步骤,而这些步骤之间的顺序、配置可能有多种变化。为了解决这个问题,建造者模式(Builder Pattern)应运而生。它可以将对象的构建过程与对象的表示分离,使得同样的构建过程可以创建不同的表示。
本文将详细介绍Python中的建造者模式,探讨其原理、适用场景、具体实现方式及优化方向,帮助开发者更好地理解和运用这一设计模式。
什么是建造者模式?
建造者模式是一种创建型设计模式,用于将一个复杂对象的构建过程分解为多个步骤,并通过一个**指挥者(Director)**来按照这些步骤来构造对象。建造者模式的核心思想是将对象的构造与对象的表示(如何创建对象)分离开来,使得同样的构建过程可以生成不同类型或配置的对象。
建造者模式的角色
建造者模式主要包括以下四个角色:
- 产品(Product):表示需要构建的复杂对象。
- 建造者(Builder):定义创建产品的抽象接口,包含构造产品不同部分的方法。
- 具体建造者(ConcreteBuilder):实现
Builder
接口,完成复杂对象各个部分的实际构造工作。 - 指挥者(Director):负责管理
Builder
,按照顺序调用Builder
中的方法来一步步构建产品对象。
建造者模式的应用场景
建造者模式适用于以下几种场景:
- 构建复杂对象:如果对象的构造步骤非常复杂(需要许多配置项),且构建过程中步骤固定但顺序不同或部分步骤可选,则适合用建造者模式。
- 隔离复杂对象的创建和使用:在某些情况下,我们希望隔离复杂对象的创建逻辑和使用逻辑,使用建造者模式可以让用户专注于如何使用对象,而不需要关心对象的构造过程。
- 多种配置对象:当一个类的实例具有不同的配置方式时,建造者模式可以帮助简化对象的创建。
典型的应用场景包括:构建复杂的UI界面、文档生成器、汽车生产、餐厅点餐系统等。
建造者模式的结构
建造者模式的基本结构可以用UML类图表示如下:
+-----------------+ +-------------------+
| Director | <----> | Builder |
+-----------------+ +-------------------+| build_part1() || build_part2() |+-------------------+|V+-------------------+| ConcreteBuilder |+-------------------+| build_part1() || build_part2() |+-------------------+|V+-------------------+| Product |+-------------------+
在这个结构中,Director
负责指挥 Builder
进行产品的创建,Builder
定义了构建产品的各个步骤,而 ConcreteBuilder
则负责实现这些步骤并生成最终的产品。
Python 实现建造者模式
接下来,我们通过一个具体的例子来实现建造者模式。假设我们要构建一个复杂的对象——房子(House),房子由不同的部分组成,如地基、墙壁、屋顶等。不同的房子类型可能有不同的部件配置(比如豪宅和普通房子)。
1. 定义产品类(Product)
房子是我们需要构建的复杂对象,因此我们首先定义一个 House
类。
class House:def __init__(self):self.foundation = Noneself.structure = Noneself.roof = Noneself.interior = Nonedef __str__(self):return f"Foundation: {self.foundation}, Structure: {self.structure}, Roof: {self.roof}, Interior: {self.interior}"
2. 定义建造者接口(Builder)
接下来,定义 Builder
抽象类,它包含构建房子不同部分的抽象方法。
from abc import ABC, abstractmethodclass HouseBuilder(ABC):@abstractmethoddef build_foundation(self):pass@abstractmethoddef build_structure(self):pass@abstractmethoddef build_roof(self):pass@abstractmethoddef build_interior(self):pass@abstractmethoddef get_house(self):pass
3. 实现具体建造者类(ConcreteBuilder)
我们需要具体的建造者类来构建不同类型的房子。比如,下面是豪宅(MansionBuilder)和普通房子(StandardHouseBuilder)的实现:
class MansionBuilder(HouseBuilder):def __init__(self):self.house = House()def build_foundation(self):self.house.foundation = "Concrete, reinforced with steel"def build_structure(self):self.house.structure = "Steel and Glass"def build_roof(self):self.house.roof = "Solar panel roof"def build_interior(self):self.house.interior = "Luxury interior with marble floors"def get_house(self):return self.houseclass StandardHouseBuilder(HouseBuilder):def __init__(self):self.house = House()def build_foundation(self):self.house.foundation = "Concrete"def build_structure(self):self.house.structure = "Wood and brick"def build_roof(self):self.house.roof = "Shingle roof"def build_interior(self):self.house.interior = "Basic interior with wooden floors"def get_house(self):return self.house
4. 定义指挥者类(Director)
Director
类负责控制构建过程,它接受一个 Builder
对象,并调用构建步骤来生成最终的产品。
class HouseDirector:def __init__(self, builder):self.builder = builderdef construct_house(self):self.builder.build_foundation()self.builder.build_structure()self.builder.build_roof()self.builder.build_interior()return self.builder.get_house()
5. 测试建造者模式
接下来,创建 HouseDirector
并传入不同的 Builder
来构建不同的房子。
# 测试建造者模式
mansion_builder = MansionBuilder()
director = HouseDirector(mansion_builder)
mansion = director.construct_house()
print("Mansion:", mansion)standard_builder = StandardHouseBuilder()
director = HouseDirector(standard_builder)
standard_house = director.construct_house()
print("Standard House:", standard_house)
输出结果:
Mansion: Foundation: Concrete, reinforced with steel, Structure: Steel and Glass, Roof: Solar panel roof, Interior: Luxury interior with marble floors
Standard House: Foundation: Concrete, Structure: Wood and brick, Roof: Shingle roof, Interior: Basic interior with wooden floors
改进建造者模式:链式调用
我们可以对建造者模式进行改进,使得它支持链式调用,这样可以使代码更加简洁、流畅。
class FluentHouseBuilder:def __init__(self):self.house = House()def build_foundation(self, foundation):self.house.foundation = foundationreturn selfdef build_structure(self, structure):self.house.structure = structurereturn selfdef build_roof(self, roof):self.house.roof = roofreturn selfdef build_interior(self, interior):self.house.interior = interiorreturn selfdef get_house(self):return self.house
使用链式调用构建房子:
builder = FluentHouseBuilder()
house = (builder.build_foundation("Concrete").build_structure("Wood and brick").build_roof("Shingle roof").build_interior("Basic interior with wooden floors").get_house())print(house)
这种方式让构建过程更加简洁,特别是在构建过程中的步骤较多时,链式调用可以减少代码冗余。
总结
建造者模式是一种非常适合构建复杂对象的设计模式,尤其是在对象的创建步骤较多、且顺序或配置变化较大的情况下。本文通过定义产品、抽象建造者、具体建造者以及指挥者,详细介绍了如何在Python中实现建造者模式。
建造者模式的好处在于它能够将对象的创建过程与其表示分离,便于扩展和维护。同时,我们还展示了如何通过链式调用的方式优化建造者模式,使代码更加简洁和可读。
希望这篇博客能帮助你更好地理解建造者模式,并能够
灵活应用到实际项目中。如果你有任何问题或建议,欢迎在评论区讨论!
相关文章:

【设计模式】Python 设计模式之建造者模式(Builder Pattern)详解
Python 设计模式之建造者模式(Builder Pattern)详解 在软件开发中,创建复杂对象往往需要多个步骤,而这些步骤之间的顺序、配置可能有多种变化。为了解决这个问题,建造者模式(Builder Pattern)应…...

微软常用运行库合集 Microsoft Visual C++ Redistributable 2023.11.13
微软常用系统运行库 Microsoft Visual C Redistributable(简称:MSVC,VB/VC,系统运行库)是Windows操作系统应用程序的基础类型库组件。此版微软常用运行库合集整合Visual C 组件安装包运行库所有版本,提供图…...

[机器视觉]basler相机使用SN编号打开相机和采集
背景分析 在项目中是用basler相机采图时,一般用的比较多的遍历相机,然后使用CreateFirstDevice这个函数获取相机,有些时候可能需要同时连接多个相机,这里一般是遍历后,再循环打开相机,根据打开相机的SN号确…...

C#使用实体类Entity Framework Core操作mysql入门:从数据库反向生成模型2 处理连接字符串
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...

Go语言基础学习(Go安装配置、基础语法)·
一、简介及安装教程 1、为什么学习Go? 简单好记的关键词和语法;更高的效率;生态强大;语法检查严格,安全性高;严格的依赖管理, go mod 命令;强大的编译检查、严格的编码规范和完整的…...

高德开放平台API调用实战指南
本文 一、地图展示1.1 地图初始化与展示1.2 自定义标记 二、路线规划2.1 驾车路线规划2.2 步行路线规划 三、定位服务3.1 使用JavaScript API进行定位3.2 IP定位 四、实时交通信息查询4.1 获取实时交通路况 五、智能调度引擎总结 一、地图展示 地图展示是开发基于地理信息系统…...

文档太大LLM处理不过来?这10种LangChain分割技术帮你搞定!
前言 RAG(检索增强生成)是一种创建基于大语言模型(LLM)应用的高效方式。它有助于生成对用户查询的准确回答。为了创建一个基于 RAG 的应用程序,我们需要执行一些操作,例如文档加载、将大文档拆分为多个小块…...

TikTok广告账号被封?常见原因及解决方法分享
TikTok广告投放往往会给我们的账号带来高效曝光和精准流量,但同时许多用户也面临着一个困扰——广告账号被封禁的问题。将在此文一起商讨TikTok广告账号被封禁的原因,分析平台的具体规定,提供解决问题的应对策略,帮助大家有效规避…...

maven聚合ssm
如果没有写过ssm项目请移步SSM后端框架搭建(有图有真相)-CSDN博客 数据库准备 create table user (id int (11),uid varchar (60),name varchar (60),age int (11),sex varchar (12) ); insert into user (id, uid, name, age, sex) values(10,202409…...

网络通信与并发编程(二)基于tcp的套接字、基于udp的套接字、粘包现象
基于tcp的套接字 文章目录 基于tcp的套接字一、套接字的工作流程二、基于tcp的套接字通信三、基于udp的套接字通信四、粘包现象 一、套接字的工作流程 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个…...

400行程序写一个实时操作系统(十):用面向对象思想构建抢占式内核
前言 通过前几章的学习,我们学会了如何为RTOS设计一个合理的内存管理算法。现在,是时候学习设计RTOS内核了。 关于RTOS内核的文章也有很多,但都有一点先射箭再化靶子的意味。要么是代码连篇解释却寥寥无几,要么是要先怎么样再怎么…...

C#学习笔记(九)
C#学习笔记(九) 第六章 面向对象编程(一)类与对象、字段与属性一、类与对象正确的理解1. 什么是类?2.什么是对象?3. 类与对象的区别 二、类的基本规范和对象使用1. 类的规范 三、类的访问修饰符(…...

意外发现!AI写作这样用,热点文章轻松超越同行90%!
做自媒体,写热点文章很重要。 热点自带流量,能很快吸引不少读者。 可很多自媒体新手很犯愁。 干货文还能勉强写出来,碰到热点文就不知咋办了。 为啥写热点文章这么难呢? 关键是得找个新颖角度切入。 要是只在网上反复复制粘贴那些…...

WPF常见容器全方位介绍
Windows Presentation Foundation (WPF) 是微软的一种用于构建Windows桌面应用程序的UI框架。WPF的布局系统基于容器,帮助开发者以灵活、响应的方式组织用户界面 (UI) 元素。本篇文章将详细介绍WPF中几种常见的容器,包括Grid、StackPanel、WrapPanel、Do…...

重置时把el-tree树节点选中状态取消
要重置 Element UI 的 el-tree 组件并取消所有节点的选中状态,可以通过以下几种方法: 使用 setCheckedKeys 方法: 如果你的树配置了 node-key 属性,可以使用 setCheckedKeys 方法来清空所有选中的节点。 this.$refs.tree.setCheck…...

服务器系统克隆技术
工作任务:克隆对象是Windows server2019 和2022的datacenter版本 条件:在已经完成安装的虚拟机上做克隆 图1-1 用两个服务器的母盘准备进行克隆 第一步:新建一个文件目录用于安放克隆好的服务器 图1-2 创建两个目录用于安放即将克隆好的服务…...

【Java】多线程 Start() 与 run() (简洁实操)
Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容:三、问题描述start() 方法run() 方法 四、解决方案:4.1 重复调用 .run()4.2 重复调用 start()4.3 正常调用…...

基于微信小程序的购物系统【附源码、文档】
博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇dz…...

AI绘画:24最新Stable Diffusion 终极炼丹宝典:从入门到精通!
前言 我是咪咪酱,以浅显易懂的方式,与大家分享那些实实在在可行之宝藏。 历经耗时数十个小时,总算将这份Stable Diffusion的使用教程整理妥当。 从最初的安装与配置,细至界面功能的详解,再至实战案例的制作…...

线性可分支持向量机的原理推导【补充知识部分】拉格朗日函数 公式解析
本文是将文章《线性可分支持向量机的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。在主文章中,有一个部分是关于补充拉格朗日对偶性的相关知识,此公式即为这部分内容。 公式 9-9 是关于拉格朗日函数 L ( x , α , β…...

csdn(最新交流群)
SEOI Chathttps://seoi.net/room/10122?kwe7cp45v此网站开放性较强,小心诈骗...

新手maven入门学习教程
MAVEN基础入门 提示:java新人的学习之路记录 学习内容: 提示:了解并会初步使用maven构建管理java项目 Maven 是一个非常流行的 Java 项目管理和构建工具。它通过提供一套标准的构建生命周期和一组预定义的目标来简化 Java 应用程序的构建过…...

React 中级阶段学习计划
React 中级阶段学习计划 目标 掌握状态管理和路由。能够调用API并处理异步数据。学会使用CSS-in-JS和CSS Modules进行样式处理。 学习内容 状态管理 React Context API Context API:用于在组件树中传递数据,避免多层props传递。示例:im…...

[产品管理-47]:产品市场调研 - 一级市场、二级市场、次级市场?
目录 一、产品销售环节的一级二级市场 1、一级市场 2、二级市场 3、一级市场与二级市场的互动关系 二、金融中的一级二级市场 1、一级市场(Primary Market)- 新股发行、定向发行 2、二级市场(Secondary Market)- 普通投资者…...

Linux零基础教程学习(黑马)
1.初识Linux 1.2远程连接Linux系统 图形化、命令行 对于操作系统的使用,有2种使用形式: 图形化页面使用操作系统 以命令的形式使用操作系统 不论是Windows还是Linux亦或是MacOS系统,都是支持这两种使用形式。 图形化:使用操作…...

一款零依赖、跨平台的流媒体协议处理工具,支持 RTSP、WebRTC、RTMP 等视频流协议的处理
大家好,今天给大家分享一款功能强大的流媒体协议处理工具go2rtc,支持多种协议和操作系统,具有零依赖、零配置、低延迟等特点。 项目介绍 go2rtc可以从各种来源获取流,包括 RTSP、WebRTC、HomeKit、FFmpeg、RTMP 等,并…...

PHP 正则验证A-Z且排除某字母
都已经找到这里来了,相信已经尝试很多办法了,那么我们直接上答案 关键正则:(?!.*[IO]) //验证5到6个大写字母且排除I和O if (preg_match(/^(?!.*[IO])[A-Z\d]{5,6}$/u, AAAAM)) {echo "匹配成功"; } else {echo "匹配失败…...

如何安全运行别人上传的Python代码?
写后端的同学,有时候需要在网站上实现一个功能,让用户上传或者编写自己的Python代码。后端再运行这些代码。 涉及到用户自己上传代码,我们第一个想到的问题,就是如何避免用户编写危险命令。如果用户的代码里面涉及到下面两行&…...

matlab相位图
% 清空工作空间和命令窗口 clear; clc; % 模拟生成时间t,位移y(t)和角位移theta(t) t linspace(0, 100, 1000); % 时间从0到100,包含1000个点 y 1e-5 * sin(2 * pi * 0.1 * t) .* exp(-0.01 * t); % 位移y(t) 振荡衰减 theta 1e-6 * cos(2 * pi * …...

C语言笔记(指针的进阶)
目录 1.字符指针 2.指针数组 3.数组指针 3.1.创建数组指针 3.2.&数组名和数组名 1.字符指针 int main() { char ch w;char* pc &ch;const char *p "abcdef";//常量字符串 产生的值就是首元素的地址//常量字符串不能被修改 因此需要加上一个…...