建造者设计模式学习

embedded/2025/1/3 19:33:10/

1.介绍

建造者模式是一种创建型设计模式,它将一个复杂对象的构建过程与它的表示分离,使得相同的构建过程可以创建不同的表示。通过分步骤地构建对象,建造者模式提供了更细粒度的控制和灵活性,特别适合需要灵活创建复杂对象的场景。

  • Builder(建造者接口):定义创建对象不同部分的抽象接口。
  • ConcreteBuilder(具体建造者):实现 Builder 接口,负责构建复杂对象的各个部分,并最终返回完整对象
  • Director(指挥者):指定复杂对象的构建顺序和步骤,协调 Builder 的调用。【指挥者可以简略】
  • Product(产品):由多个部件组成的复杂对象,是建造的最终结果。

2.简单例子

标准的例子:

#include <iostream>
#include <string>// Product: 复杂对象
class Computer {
private:std::string CPU;std::string GPU;std::string RAM;std::string Storage;public:void setCPU(const std::string& cpu) { CPU = cpu; }void setGPU(const std::string& gpu) { GPU = gpu; }void setRAM(const std::string& ram) { RAM = ram; }void setStorage(const std::string& storage) { Storage = storage; }void show() const {std::cout << "Computer Configuration:\n"<< "CPU: " << CPU << "\n"<< "GPU: " << GPU << "\n"<< "RAM: " << RAM << "\n"<< "Storage: " << Storage << "\n";}
};// Builder: 抽象建造者
class ComputerBuilder {
public:virtual ~ComputerBuilder() = default;virtual void buildCPU() = 0;virtual void buildGPU() = 0;virtual void buildRAM() = 0;virtual void buildStorage() = 0;virtual Computer* getResult() = 0;
};// ConcreteBuilder: 具体建造者
class GamingComputerBuilder : public ComputerBuilder {
private:Computer* computer;public:GamingComputerBuilder() { computer = new Computer(); }~GamingComputerBuilder() { delete computer; }void buildCPU() override { computer->setCPU("Intel i9"); }void buildGPU() override { computer->setGPU("NVIDIA RTX 4090"); }void buildRAM() override { computer->setRAM("32GB DDR5"); }void buildStorage() override { computer->setStorage("2TB SSD"); }Computer* getResult() override {Computer* result = computer;computer = nullptr; // 防止重复释放return result;}
};// Director: 指挥者
class Director {
private:ComputerBuilder* builder;public:void setBuilder(ComputerBuilder* b) { builder = b; }Computer* construct() {builder->buildCPU();builder->buildGPU();builder->buildRAM();builder->buildStorage();return builder->getResult();}
};// 客户端代码
int main() {Director director;GamingComputerBuilder gamingBuilder;// 设置建造者director.setBuilder(&gamingBuilder);// 构建计算机Computer* gamingComputer = director.construct();// 显示结果gamingComputer->show();delete gamingComputer;return 0;
}

// 其实director有点死板,它每次都要使用不同的builder,才能创建不同的对象,直接把创建产品的任务交给builder自己也行。

2.1 链式编程

https://zhuanlan.zhihu.com/p/143101326

关键点是builder的函数直接返回产品对象

// 产品类
public class KFC {//套餐必点private String hamburger;private String chips;//套餐选点private String chicken;private String cola;private String pizza;public KFC(String hamburger,String chips){this.hamburger = hamburger;this.hamburger = chips;}public void setChicken(String chicken) {this.chicken = chicken;}public void setCola(String cola) {this.cola = cola;}public void setPizza(String pizza) {this.pizza = pizza;}
};// 抽象builder
public abstract class Builder {abstract Builder setChicken();abstract Builder setCola();abstract Builder setPizza();abstract KFC getKFC();
}// 具体builder
public class ConcreteBuilder extends Builder {KFC kfc;public ConcreteBuilder(String hamburger,String chips){kfc = new KFC(hamburger,chips);}@OverrideBuilder setChicken() {kfc.setChicken("鸡腿");return this; // 返回自己,可以链式调用}@OverrideBuilder setCola() {kfc.setCola("可乐");return this;}@OverrideBuilder setPizza() {kfc.setPizza("披萨");return this;}@OverrideKFC getKFC() {return kfc;}
}// main函数
public class BTest {public static void main(String[] args) {// 实例化一个具体的builder类,通过它返回一个具体对象KFC kfc = new ConcreteBuilder("汉堡","薯条").setChicken().setCola().getKFC();}
}

3.项目实例

gRPC通过builder构建server对象,

这里的builder也不是一个抽象建造者,而是一个具体的类,所以它是只有具体建造者和产品类,也可以理解为将director和builder合二为一了,都合到builder里面了。设计模式是可以简化的,不是那么死板的。


http://www.ppmy.cn/embedded/150637.html

相关文章

CSS系列(39)-- Shapes详解

前端技术探索系列&#xff1a;CSS Shapes详解 ✨ 致读者&#xff1a;探索形状布局的艺术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS Shapes&#xff0c;这个强大的形状布局特性。 基础形状 &#x1f680; 圆形与椭圆 /* 基础圆形 */ .circle {widt…

linux主机网卡名称不一致导致网卡up报错解决办法、正确root密码无法登录控制台解决办法、普通用户sudo到root方法

文章目录 网卡不一致解决办法说明解决办法正确root密码无法登录控制台解决办法说明解决办法普通用户sudo到root方法说明sudo办法网卡不一致解决办法 说明 如下,用户自定义的镜像生成的虚拟机,网卡名称不一致,估计是做镜像的时候有问题,重启后网卡信息被还原了 up就报错 …

Tailwind CSS 实战:现代登录注册页面开发

在前端开发中&#xff0c;登录注册页面是最常见的需求之一。一个设计精美、交互友好的登录注册页面不仅能提升用户体验&#xff0c;还能增加产品的专业度。本文将详细介绍如何使用 Tailwind CSS 开发一个现代化的登录注册页面。 设计思路 在开始编码之前&#xff0c;我们先明…

2024年终总结--在悲催中寻找希望的光

大家好&#xff0c;我是 V 哥。时光荏苒&#xff0c;岁月如梭&#xff0c;转眼间2024年已接近尾声。回首这一年&#xff0c;心中感慨万千。2024年是悲催的一年、心酸的一年、纠结的一年&#xff0c;在这充满挑战的大环境下&#xff0c;IT行业受到了巨大的冲击&#xff0c;就业市…

u3d插件之Easy Touch

一.Easy Touch应用场合 1.1 各种触摸事件的处理(触摸&#xff0c;点击&#xff0c;双击&#xff0c;滑动等) 1.2 需要使用一些方向型控件的场合(摇杆&#xff0c;方向柄&#xff0c;按钮等) 二.导入Easy Touch 从Asset Store或其他web下载Easy Touch资源包&#xff0c;拖拽…

LeetCode31. 下一个排列(2024冬季每日一题 41)

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&#xff…

Kafka安全优化文档:漏洞修复到安全加固

文章目录 1.1.漏洞修复1.1.1.Apache Kafka反序列化漏洞1.1.2.pm2-kafka代码执行漏洞1.1.3.Apache Kafka安全绕过漏洞1.1.4.Apache Kafka Distribution - Schema Repository跨站请求伪造漏洞1.1.5.Apache Kafka输入验证错误漏洞的补丁1.1.6.Apache Kafka信息泄露漏洞1.1.7.Apach…

Rabbitmq追问1

如果消费端代码异常&#xff0c;未手动确认&#xff0c;那么这个消息去哪里 2024-12-31 21:19:12 如果消费端代码发生异常&#xff0c;未手动确认&#xff08;ACK&#xff09;的情况下&#xff0c;消息的处理行为取决于消息队列的实现和配置&#xff0c;以下是基于 RabbitMQ …