3 生成器(Builder)模式

devtools/2025/1/16 11:12:47/

生成器模式

1.1 分类

(对象)创建型

1.2 提出问题

  1. 构造一个房屋,需要考虑是否有车库,游泳池,花园,雕塑等,需要对诸多成员变量进行初始化工作。都写在构造函数里?每种可能都创建一个新的类?
  2. 相同的步骤需要能够产生不同的产品,例如使用木头和玻璃盖出来的是普通住房。用黄金和水晶建造出来的是宫殿。

1.3 解决方案

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。即将对象构造代码从产品类中抽取出来,并将其放在一个名为Builder的独立对象中。

1.4 实现类图

在这里插入图片描述

  1. 生成器(Builder):声明通用的产品构造步骤。
  2. 具体生成器(Concrete Builders):提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。
  3. 产品(Products):最终生成的对象。由不同生成器构造的产品无需属于同一类层次结构或接口。
  4. 主管(Director):定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置。
  5. 客户端(Client):必须将某个生成器对象与主管类关联。一 般情况下,只需通过主管类构造函数的参数进行一次性关联即可。

:程序中并不一定需要主管类。客户端代码可直接以特定顺序调用创建步骤。不过,主管类中非常适合放入各种例行构造流程,以便在程序中反复使用。
:不同于其他创造模式,不同的ConcreteBuilder可以生产不相关的产品。Product1和Product2可以不遵循相同的接口。因此在C++这样的静态类型语言中,getResult方法不能放到Builder接口里。

1.5 示例代码

#include <iostream>
#include <vector>
#include <string>
//产品1
class SimpleHouse {
public:std::vector<std::string> m_parts;void printParts() const {std::cout << "SimpleHouse 包括:\n";for (int i = 0; i < m_parts.size(); ++i) {std::cout << m_parts[i] << std::endl;}std::cout << "----------------------\n";}
};
//生成器
class Builder {
public:virtual ~Builder() {}virtual void reset() = 0;virtual void makeBaseHouse() = 0;virtual void makeGarage() = 0;virtual void makePool() = 0;
};
//concreteBuilder1,施工队
class SimpleHouseBuilder : public Builder {
private:SimpleHouse* m_simplehouse;
public:SimpleHouseBuilder() {reset();}~SimpleHouseBuilder() { delete m_simplehouse; }void reset() override{m_simplehouse = new SimpleHouse();}virtual void makeBaseHouse() override{m_simplehouse->m_parts.push_back("BaseHouse");}virtual void makeGarage() override {m_simplehouse->m_parts.push_back("Garage");}virtual void makePool() override {m_simplehouse->m_parts.push_back("Pool");}SimpleHouse* getResult() {SimpleHouse* result = m_simplehouse;reset();return result;}
};
//主管:负责流程
class Director {
private:Builder* m_builder;
public:void setBuilder(Builder* builder) {m_builder = builder;}void makeSimpleHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();}void makeFullFuncHouse() {m_builder->makeBaseHouse();m_builder->makeGarage();m_builder->makePool();}
};
//客户端(也可以封装成类)
void client(Director* director) {std::cout << "客户自己设计流程:---------------------\n";SimpleHouseBuilder* builder = new SimpleHouseBuilder();builder->makeBaseHouse();builder->makeGarage();SimpleHouse * simpleHouse= builder->getResult();simpleHouse->printParts();delete simpleHouse;std::cout << "主管负责设计流程:---------------------\n";director->setBuilder(builder);director->makeFullFuncHouse();simpleHouse = builder->getResult();simpleHouse->printParts();delete simpleHouse;delete builder;
}
int main()
{Director director;client(&director);
}

1.6 举个栗子

下面关于生成器模式的例子,演示了如何复用相同的对象构造代码来生成不同类型的产品:例如汽车(Car)和其相应的使用手册(Manual)。
在这里插入图片描述

1.7 总结

  1. 将对象的构造过程分解到若干个步骤,这就使程序可以更加精细,有效地控制整个对象的构造。
  2. 生成不同形式的产品时,可以复用相同的制造代码。
  3. 单一职责原则。可以将复杂构造代码从产品的业务逻辑中分离出来。
  4. 当增加新的具体生成器时,不必修改主管的代码,满足开闭原则。
  5. 缺点:如果产品之间的差异性很大,则不适合使用建造者模式,使用范围受到一定的限制。

http://www.ppmy.cn/devtools/150935.html

相关文章

Python自学 - 标准库介绍

<< 返回目录 1 Python自学 - 标准库介绍 标准库是安装Python时自带的一些模块集合&#xff0c;集成了丰富的功能&#xff0c;避免用户反复造轮子&#xff0c;这极大的提高了生产效率&#xff01; 1.1 几种常用的标准库 1.1.1 os 模块 提供了与操作系统交互的接口&…

java_抽象类最佳实践-模板设计模式

基本介绍 模板设计模式可解决的问题 最佳实践 Template类 package com.hspedu.abstract_; abstract public class Template { //抽象类-模板设计模式public abstract void job();//抽象方法public void calculateTime() {//实现方法&#xff0c;调用 job 方法//得到开始的时间…

线程池底部工作原理

线程池内部是通过线程和队列实现的&#xff0c;当我们通过线程池处理任务时&#xff1a; 如果线程池中的线程数量小于corePoolSize&#xff0c;无论是否有处于空闲的线程&#xff0c;都创建新的线程来处理被添加的任务。 如果线程池中的线程数量等于corePoolSize&#xff0c;…

ros2笔记-6.2 使用urdf创建机器人模型

本节主要跟着小鱼老师的视频操作&#xff0c;不同的仿真平台有不同的建模语言&#xff0c;但是几乎都支持URDF。 本节使用URDF创建一个机器人模型。 6.2.1 帮机器人创建一个身体 URDF使用XML来描述机器人的结构和传感器、执行器等信息。 在chapt6/chap6_ws/src创建功能包:r…

线程间通信

线程间通信&#xff08;Inter-Thread Communication, 简称ITC&#xff09;是指在多线程编程中&#xff0c;不同线程之间如何交换信息或协调彼此的行为。良好的线程间通信机制是构建高效、可靠的并发程序的关键。Java语言提供了多种内置工具和库来支持线程间的通信&#xff0c;包…

0098__Windbg调试dump文件

Windbg调试dump文件_windbg怎样调试dmp文件-CSDN博客

使用RSyslog将Nginx Access Log写入Kafka

个人博客地址&#xff1a;使用RSyslog将Nginx Access Log写入Kafka | 一张假钞的真实世界 环境说明 CentOS Linux release 7.3.1611kafka_2.12-0.10.2.2nginx/1.12.2rsyslog-8.24.0-34.el7.x86_64.rpm 创建测试Topic $ ./kafka-topics.sh --zookeeper 192.168.72.25:2181/k…

如何学好数据结构?

相信很多小伙伴们&#xff0c;刚开始接触数据结构这一门学科的时候呢&#xff0c;害怕甚至是厌烦&#xff0c;感觉非常的难&#xff0c;不好学,那么今天呢我就我给大家讲解一下如何去学好数据结构 在编程的世界里&#xff0c;数据结构是基石&#xff0c;它决定了程序的效率和可…