【再谈设计模式】建造者模式~对象构建的指挥家

一、引言

         在软件开发的世界里,创建对象是一项基本且频繁的操作。然而,当对象的构造变得复杂,涉及众多属性和初始化步骤时,传统的构造函数方式往往会让代码陷入混乱的泥沼。就如同搭建一座复杂的建筑,若没有合理的规划和组织,各个部件随意堆砌,最终的结果可能是摇摇欲坠。在这种情况下,建造者设计模式就如同一位经验丰富的建筑师,为我们提供了一种有条不紊地构建复杂对象的方法,它将构建过程与对象的最终表示分离开来,使我们能够轻松应对复杂对象创建的挑战。

二、定义与描述

        建造者设计模式属于创建型设计模式,它将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。这种模式允许你使用相同的构建代码创建不同类型和配置的对象。

三、抽象背景

        在软件开发中,经常会遇到创建复杂对象的情况。如果直接使用构造函数或者简单的工厂方法来创建对象,可能会导致构造函数参数过多,代码难以维护和理解。例如,创建一个包含多个属性(如房屋的面积、房间数量、装修风格等)的对象时,直接构造可能会变得非常复杂。

四、适用场景与现实问题

解决复杂对象创

        当创建的对象具有多个可选参数或者复杂的初始化过程时,建造者模式可以清晰地分离构建步骤,使代码更易读和维护。
        例如,在创建一个汽车对象时,汽车可能有不同的颜色、型号、配置(如自动或手动档)等属性。使用建造者模式可以方便地根据用户需求组合这些属性来创建汽车对象。


对象创建过程的定制化
        如果需要根据不同的条件或需求定制对象的创建过程,建造者模式很有用。
比如在构建一份个性化的餐食订单,根据顾客的不同口味选择(主食、配菜、饮料等)构建不同的餐食对象。

五、现实生活的例子

以建造房屋为例。
        建造一座房子是一个复杂的过程,包括打地基、砌墙、盖屋顶等步骤。
有不同类型的房子,如别墅、公寓等,它们的建造过程基本相同,但最终呈现的样子(表示)不同。


        建筑工人(建造者)按照建筑师(导演者)的要求,通过相同的基本建造步骤(打地基、砌墙、盖屋顶等),但使用不同的材料或者设计风格,建造出不同类型的房子。

六、初衷与问题解决

初衷
        为了应对复杂对象的创建,将对象的构建过程从对象本身的表示中分离出来,提高代码的可维护性和可扩展性。
问题解决
        解决了构造函数参数过多的问题。例如,原本创建一个复杂对象可能需要一个包含十几个参数的构造函数,使用建造者模式后,可以通过多个简单的设置方法来逐步构建对象。
便于对象的定制化创建,满足不同用户或场景的需求。

七、代码示例

Java示例

// 产品类:房屋
class House {private String foundation;private String walls;private String roof;public House(String foundation, String walls, String roof) {this.foundation = foundation;this.walls = walls;this.roof = roof;}public String toString() {return "House with foundation: " + foundation + ", walls: " + walls + ", roof: " + roof;}
}// 抽象建造者
abstract class HouseBuilder {protected House house;public House getHouse() {return house;}public abstract void buildFoundation();public abstract void buildWalls();public abstract void buildRoof();
}// 具体建造者:别墅建造者
class VillaBuilder extends HouseBuilder {public VillaBuilder() {house = new House("", "", "");}@Overridepublic void buildFoundation() {house.foundation = "Deep and large foundation for villa";}@Overridepublic void buildWalls() {house.walls = "High - quality stone walls for villa";}@Overridepublic void buildRoof() {house.roof = "Sloping roof for villa";}
}// 导演者
class HouseDirector {public House constructHouse(HouseBuilder builder) {builder.buildFoundation();builder.buildWalls();builder.buildRoof();return builder.getHouse();}
}// 测试
public class BuilderPatternJava {public static void main(String[] args) {HouseDirector director = new HouseDirector();HouseBuilder villaBuilder = new VillaBuilder();House villa = director.constructHouse(villaBuilder);System.out.println(villa);}
}

C++示例

#include <iostream>
#include <string>// 产品类:汽车
class Car {
private:std::string color;std::string model;std::string gearType;public:Car(std::string color, std::string model, std::string gearType) : color(color), model(model), gearType(gearType) {}friend std::ostream& operator<<(std::ostream& os, const Car& car) {os << "Car - Color: " + car.color + ", Model: " + car.model + ", Gear Type: " + car.gearType;return os;}
}// 抽象建造者
class CarBuilder {
protected:Car* car;public:Car* getCar() {return car;}virtual void buildColor() = 0;virtual void buildModel() = 0;virtual void buildGearType() = 0;
}// 具体建造者:跑车建造者
class SportsCarBuilder : public CarBuilder {
public:SportsCarBuilder() {car = new Car("", "", "");}void buildColor() override {car->color = "Red";}void buildModel() override {car->model = "Sports Model";}void buildGearType() override {car->gearType = "Manual";}
}// 导演者
class CarDirector {
public:Car* constructCar(CarBuilder* builder) {builder->buildColor();builder->buildModel();builder->buildGearType();return builder->getCar();}
}// 测试
int main() {CarDirector director;CarBuilder* sportsCarBuilder = new SportsCarBuilder();Car* sportsCar = director.constructCar(sportsCarBuilder);std::cout << *sportsCar << std::endl;delete sportsCarBuilder;delete sportsCar;return 0;
}

Python示例

# 产品类:披萨
class Pizza:def __init__(self):self.dough = Noneself.sauce = Noneself.toppings = []def __str__(self):topping_str = ', '.join(self.toppings)return f"Pizza with {self.dough} dough, {self.sauce} sauce and {topping_str} toppings"# 抽象建造者
class PizzaBuilder:def __init__(self):self.pizza = Pizza()def get_pizza(self):return self.pizzadef build_dough(self):passdef build_sauce(self):passdef add_toppings(self):pass# 具体建造者:夏威夷披萨建造者
class HawaiianPizzaBuilder(PizzaBuilder):def build_dough(self):self.pizza.dough = "Thin"def build_sauce(self):self.pizza.sauce = "Tomato"def add_toppings(self):self.pizza.toppings = ["Ham", "Pineapple"]# 导演者
class PizzaDirector:def construct_pizza(self, builder):builder.build_dough();builder.build_sauce();builder.add_toppings();return builder.get_pizza()# 测试
if __name__ == "__main__":director = PizzaDirector()builder = HawaiianPizzaBuilder()pizza = director.construct_pizza(builder)print(pizza)

Go示例

// 产品类:电脑
type Computer struct {cpu    stringmemory stringstorage string
}func (c Computer) String() string {return "Computer with CPU: " + c.cpu + ", Memory: " + c.memory + ", Storage: " + c.storage
}// 抽象建造者
type ComputerBuilder interface {BuildCPU()BuildMemory()BuildStorage()GetComputer() Computer
}// 具体建造者:游戏电脑建造者
type GamingComputerBuilder struct {computer Computer
}func (g *GamingComputerBuilder) BuildCPU() {g.computer.cpu = "High - performance CPU"
}func (g *GamingComputerBuilder) BuildMemory() {g.computer.memory = "Large - capacity memory"
}func (g *GamingComputerBuilder) BuildStorage() {g.computer.storage = "High - speed storage"
}func (g *GamingComputerBuilder) GetComputer() Computer {return g.computer
}// 导演者
type ComputerDirector struct{}func (d ComputerDirector) ConstructComputer(builder ComputerBuilder) Computer {builder.BuildCPU()builder.BuildMemory()builder.BuildStorage()return builder.GetComputer()
}// 测试
func main() {director := ComputerDirector{}builder := &GamingComputerBuilder{}computer := director.ConstructComputer(builder)println(computer)
}

八、建造者设计模式的优缺点

优点

解耦对象的构建和表示
        使得构建过程和最终对象的表示可以独立变化,便于代码的维护和扩展。
易于创建复杂对象
        可以分步骤构建对象,代码结构清晰,易于理解和编写。
代码复用性高
        可以复用相同的构建步骤来创建不同类型的对象。

缺点

增加代码复杂度
        需要定义多个类(建造者、导演者、产品类等),对于简单的对象创建可能会使代码过于复杂。
可能存在多余的建造者类
        如果对象的构建方式比较固定,可能不需要那么多不同的建造者类,会造成代码冗余。

九、建造者设计模式的升级版

链式建造者模式(Fluent Builder Pattern)

        在传统建造者模式的基础上,将建造者方法的返回值设置为建造者本身,这样可以实现链式调用。
        例如在Java中,可以将建造者方法返回 this。
        优点是使代码更加紧凑和易于阅读,特别是在构建对象时可以在一行中完成多个属性的设置。
        缺点是如果构建过程中出现错误,调试可能会比较复杂,因为链式调用可能会隐藏一些中间状态。
        建造者设计模式在处理复杂对象创建方面有着独特的优势,通过合理的运用可以提高代码的质量和可维护性,并且在需要定制化创建对象的场景下非常实用。

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

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

相关文章

三、模板与配置(下)

三、模板与配置 8、WXSS模板样式-全局样式和局部样式 类型说明适用情景注意点全局样式定义在 app.wxss 中的样式&#xff0c;作用于每一个页面。当有一些通用的样式规则需要应用于整个小程序时&#xff0c;比如全局的字体大小、颜色、布局等。全局样式可能会被局部样式覆盖&a…

SQL面试题——抖音SQL面试题 主播播出时长

主播播出时长 现有如下数据,主播id、房间号、播出的批次号,每个批次号进出房间的时间戳、分区时间: 每一次直播都有一个上播和下播,每个房间里,同一个批次号会有两条数据,分别记录了上播和下播时间,求每个主播的播出时长? 通过上面的数据,可以清晰的看出,同一个批次…

大语言模型LLM综述

一、LM主要发展阶段 1.1、统计语言模型SLM 基于统计学习方法&#xff0c;基本思想是基于马尔可夫假设HMM建立词概率预测模型。如n-gram语言模型 1.2、神经语言模型NLM 基于神经网络来做词的分布式表示。如word2vec模型 1.3、 预训练语言模型PLM 预训练一个网络模型来做词表…

用 Python 从零开始创建神经网络(七):梯度下降(Gradient Descent)/导数(Derivatives)

梯度下降&#xff08;Gradient Descent&#xff09;/导数&#xff08;Derivatives&#xff09; 引言1. 参数对输出的影响2. 斜率&#xff08;The Slope&#xff09;3. 数值导数&#xff08;The Numerical Derivative&#xff09;4. 解析导数&#xff08;The Analytical Derivat…

防爆手机市场“百花齐放”,该怎么选?

在危险作业场景&#xff0c;如石化煤矿&#xff0c;通讯设备采购关系到提高生产效率‌&#xff0c;保障安全生产‌&#xff0c;‌符合法规要求‌。在应急救援通信场景&#xff0c;通讯设备采购&#xff0c;与保障救援行动的效率和准确性息息相关。而通信设备的性能参数是评估其…

似然函数解析

从贝叶斯定理引出似然函数 最大似然估计用来估计均值方差的 文心对似然函数的解释&#xff0c;注意 抛出正反的概率&#xff0c;就是固定均值方差的条件概率密度了

记录配置ubuntu18.04下运行ORBSLAM3的ros接口的过程及执行单目imu模式遇到的问题(详细说明防止忘记)

今天的工作需要自己录制的数据集来验证昨天的标定结果 用ORBSLAM3单目imu模式运行&#xff0c;mentor给的是一个rosbag格式的数据包&#xff0c;配置过程出了几个问题记录一下&#xff0c;沿配置流程写。 一.orbslam3编译安装 1.首先是安装各种依赖 这里不再赘述&#xff0…

实验5:网络设备发现、管理和维护

实验5&#xff1a;网络设备发现、管理和维护 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…

前端(2)——快速入门CSS

参考&#xff1a; 罗大富 CSS 参考手册 | 菜鸟教程 CSS 参考手册 1. CSS CSS全名是层叠样式表&#xff0c;中文名层叠样式表。用于定义网页样式和布局的样式表语言。 通过 CSS&#xff0c;你可以指定页面中各个元素的颜色、字体、大小、间距、边框、背景等样式&#xff0c;…

yolo标签自动标注(使用python和yolo方法)

yolo代码自动标注 1.引言1.初阶“自动标注”&#xff0c;给每个图像都生成一个固定的标注文件&#xff0c;进而在labglimg中对矩形框进行微调&#xff0c;减少标注的工作量2.高阶自动标注&#xff0c;利用我们训练好的&#xff08;但是没有特别精准的&#xff09;yolo文件先对每…

jmeter常用配置元件介绍总结之线程组

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之线程组 1.线程组(用户)1.1线程组1.1.setUp线程组和tearDown线程组1.2.Open Model Thread Group(开放模型线程组)1.3.bzm - Arrivals Thread Group(到达线程组)1.4.jpgc - Ultimate Thread Group(终极线程组)1.5.jpgc - St…

spring gateway 动态路由

##yml配置 spring:application:name: public-gateway # cloud: # gateway: # routes: # - id: mybatis-plus-test # 路由的唯一标识 # uri: http://192.168.3.188:9898 # 目标服务的地址 # predicates: # - Path/test/** # 匹配…

NVT新能德科技入职测评SHL题库更新:数字推理+演绎推理高分答案、真题解析

新能德的入职Verify测评主要考察应聘者的逻辑推理能力、数学能力、数据分析能力以及处理信息的能力。根据搜索结果&#xff0c;测评通常包含以下几个部分&#xff1a; 1. **语言理解**&#xff1a;这部分包括阅读理解、逻辑填空和语句排序。要求应聘者在17分钟内完成30题&#…

学法减分交管12123模拟练习小程序源码前端和后端和搭建教程

交管推出个学法减分&#xff0c;每个驾驶员可以把被扣的6分&#xff0c;以看视频答题的形式学习回来&#xff0c;然后答题这个一共二十道题每道题60秒&#xff0c;有好多人不会&#xff0c;用咱们的小程序就可以模拟练习强化练习&#xff0c;还有拍照识别题目找到正确答案&…

element-plus <el-date-picker>日期选择器踩坑!!!!

我怎么一上午踩两个坑&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;大声bb&#xff09; 原来的vue2老项目是这样写的 <el-form-item label"时间" prop"time"><el-date-pickerv-model"addForm.time"typ…

JS的学习与使用

JS的学习与使用 一 什么是Javascript&#xff1f; Javascript是一门跨平台&#xff0c;面向对象的脚本语言&#xff0c;是用来控制网页行为的&#xff0c;它能使网页可以交互 java与Javascript是完全不同的语言&#xff0c;不论是概念还是设计&#xff0c;但是基础语法类似 E…

ubuntu20.04 解决Pytorch默认安装CPU版本的问题

ubuntu20.04 解决Pytorch默认安装CPU版本的问题 在使用Anaconda安装支持CUDA的PyTorch版本时&#xff0c;遇到只能安装CPU版本的PyTorch是一个常见问题。这通常由于Anaconda环境配置、镜像源设置不当或版本匹配问题导致。以下是详尽的解决方案和步骤&#xff0c;以确保能够正确…

【操作系统】守护进程

一、守护进程的概念 守护进程是一个在后台运行并且不受任何终端控制的进程 二、自己实现守护进程 1.预备知识 &#xff08;1&#xff09;/dev/null /dev/null是一个特殊的设备文件&#xff0c;往这个文件里写不进去任何数据&#xff0c;也读不出来任何数据 因此&#xff0…

【数据结构与算法】第12课—数据结构之归并排序

文章目录 1. 归并排序2. 计数排序3. 排序算法复杂度及稳定性分析在这里插入图片描述 1. 归并排序 分治法&#xff08;Divide and Conquer&#xff09;是一种重要的算法设计策略&#xff0c;其核心思想是将一个复杂的大问题分解为若干个小规模的子问题&#xff0c;递归地解决这些…

【安全通信】告别信息泄露:搭建你的开源视频聊天系统briefing

文章目录 前言1.关于briefing2.本地部署briefing3.使用briefing4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定briefing公网地址 前言 在这个信息爆炸的时代&#xff0c;视频聊天几乎成了我们日常沟通的标配。但你是否曾在视频会议中感到不安&#xff0c;担心自己的私…