C++设计模式|创建型 4.建造者模式

1.什么是建造者模式?

建造者模式(也被成为生成器模式),是一种创建型设计模式,软件开发过程中有的时候需要创建很复杂的对象,而建造者模式的主要思想是将对象的构建过程分为多个步骤,并为每个步骤定义一个抽象的接口具体的构建过程由实现了这些接口的具体建造者类来完成同时有一个指导者类负责协调建造者的工作,按照一定的顺序或逻辑来执行构建步骤,最终生成产品。

举个例子,假如我们要创建一个计算机对象,计算机由很多组件组成,例如 CPU、内存、硬盘、显卡等。每个组件可能有不同的型号、配置和制造,这个时候计算机就可以被视为一个复杂对象,构建过程相对复杂,而我们使用建造者模式将计算机的构建过程封装在一个具体的建造者类中,而指导者类则负责指导构建的步骤和顺序。每个具体的建造者类可以负责构建不同型号或配置的计算机,客户端代码可以通过选择不同的建造者来创建不同类型的计算机,这样就可以根据需要构建不同表示的复杂对象,更加灵活。

2.建造者模式的基本结构

  • 产品Product:被构建的复杂对象, 包含多个组成部分。
  • 抽象建造者Builder: 定义构建产品各个部分的抽象接口和一个返回复杂产品的方法getResult
  • 具体建造者Concrete Builder实现抽象建造者接口,构建产品的各个组成部分,并提供一个方法返回最终的产品。
  • 指导者Director调用具体建造者的方法,按照一定的顺序或逻辑来构建产品。

在客户端中,通过指导者来构建产品,而并不和具体建造者进行直接的交互。 

3.建造者模式的大致流程

  1. 定义产品类:产品类应该包含多个组成部分,这些部分的属性和方法构成了产品的接口。
  2. 定义抽象建造者接口:创建一个接口,包含构建产品各个部分的抽象方法。这些方法通常用于设置产品的各个属性。
  3. 创建具体建造者:实现抽象建造者接口,构建具体的产品。
  4. 定义Director类: 指导者类来控制构建产品的顺序和步骤。
  5. 客户端使用建造者模式:在客户端中创建【具体建造者对象】和【指导者对象】,通过指导者来构建产品。

4.建造者模式的使用场景 

使用建造者模式有下面几处优点:

  • 使用建造者模式可以将一个复杂对象的构建与其表示分离,通过将构建复杂对象的过程抽象出来,可以使客户端代码与具体的构建过程解耦

  • 同样的构建过程可以创建不同的表示,可以有多个具体的建造者(相互独立),可以更加灵活地创建不同组合的对象。

建造者模式适用于复杂对象的创建,当对象构建过程相对复杂时可以考虑使用建造者模式,但是当产品的构建过程发生变化时,可能需要同时修改指导类和建造者类,这就使得重构变得相对困难(缺点)。

5.C++实现建造者模式

【设计模式专题之建造者模式】4. 自行车加工 (kamacoder.com)icon-default.png?t=N7T8https://kamacoder.com/problempage.php?pid=1084

题目描述:

小明家新开了一家自行车工厂,用于使用自行车配件(车架 frame车轮 tires )进行组装定制不同的自行车,包括山地车和公路车。

山地车使用的是Aluminum Frame(铝制车架)和 Knobby Tires(可抓地轮胎),公路车使用的是 Carbon Frame (碳车架)和 Slim Tries。

现在它收到了一笔订单,要求定制一批自行车,请你使用【建造者模式】告诉小明这笔订单需要使用那些自行车配置吧。

输入描述:

输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示订单的数量。 

接下来的 N 行,每行输入一个字符串,字符串表示客户的自行车需求。

字符串可以包含关键词 "mountain" 或 "road",表示客户需要山地自行车或公路自行车。例如:

3
mountain
road
mountain

输出描述:

对于每笔订单,输出该订单定制的自行车配置。例如:

Aluminum Frame Knobby Tires
Carbon Frame Slim Tires
Aluminum Frame Knobby Tires

在本例中:产品为自行车,所以可以有两个具体建造者山地车建造者公路车建造者

按照本文所述的建造者模式的大致流程,写出C++代码如下:

#include<iostream>
#include<string>
using namespace std;

//按照建造者模式的流程来实现
//1、定义产品类,要包含产品的属性和设置方法
class Bike{
    //友元函数加左移运算符重载,用来链式输出自定义数据类型的内容。
    //通常类内只做友元函数的声明,具体实现要写在类外
    friend ostream& operator<<(ostream & out, const Bike & bike);
private:
    //自行车的属性有车架frame和车轮tires
    string frame;
    string tires;
public:   
    //定义接口方法,为属性设置具体的形式
    void setFrame(const string& frame){
        this->frame = frame;
    }
    
    void setTires(const string& tires){
        this->tires = tires;
    }
    

};
//
ostream& operator<<(ostream & out, const Bike & bike)
{
    out<<bike.frame<<" "<<bike.tires;
    return out;
}


//2.定义抽象建造者接口:创建一个接口,包含构建产品各个部分的抽象方法
class AbstractBikeBuilder{
public:
    //定义构建自行车的抽象接口
   virtual void bulidFrame() = 0;
   virtual void buildTires() = 0;
   virtual Bike&  getResult() = 0;
};


//3.定义具体建造者
//3.1 定义具体山地车建造者
class MountainBikeBuilder : public AbstractBikeBuilder{
private:
    Bike bike;
public:
    void bulidFrame() override {
        bike.setFrame("Aluminum Frame");
    
    }
    
    void buildTires() override{
        bike.setTires("Knobby Tires");
    }
    
    Bike&  getResult() override{
        return bike;
    }
    
};


//3.2 定义具体公路车建造者
class RoadBikeBuilder : public AbstractBikeBuilder{
private:
    Bike bike;
public:
    void bulidFrame() override {
        bike.setFrame("Carbon Frame");
    
    }
    
    void buildTires() override{
        bike.setTires("Slim Tires");
    }
    
    Bike&  getResult() override{
        return bike;
    }
    
};


//4.定义指导者类来控制构建产品的顺序和步骤
class BikeDirector{
public:
//需要通过指导者类来调用建造者
    Bike& construct(AbstractBikeBuilder &builder){
        builder.bulidFrame();
        builder.buildTires();
        return builder.getResult();
    }
};

int main()
{
    int N;
    cin>>N;
    
    
    for(int i=0; i < N; i++)
    {
        string bikeType;
        cin>>bikeType;
        
        
        AbstractBikeBuilder *builder;
        //根据输入,创建不同的具体建造者
        if(bikeType == "mountain"){
            builder = new MountainBikeBuilder();
        }
        else if(bikeType == "road"){
            builder = new RoadBikeBuilder();
        }

        //指导者通过具体建造者来指导产品生产
        BikeDirector director;
        //接口传入具体的建造者指针,该函数内部通过建造者指针调用生产过程
        Bike bike = director.construct(*builder);
        //《《运算符的重载实现了自定义数据的输出
        cout<<bike<<endl;
        
        delete builder;
    }
    
    return 0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

共享WiFi贴推广有哪些好处?一文说清

随着科技发展&#xff0c;更加智能高效便捷的共享wifi贴开始越来越多的取代了传统的wifi连接方法。 因为传统的连接WiFi方式确实存在一些不便之处。客人需要手动搜索店铺的WiFi&#xff0c;然后输入复杂的密码进行连接。这一过程不仅繁琐&#xff0c;而且容易出错。有时&#…

稳了!麒麟信安云应用助力国产化生态平稳过渡

2016年国家提出了安全可控体系并大力推进基础硬件、基础软件及应用软件的国产化建设进程。各行业及企事业单位加大国产设备及软硬件的采购力度&#xff0c;逐步完成国产化转型。而操作系统作为上层应用的载体&#xff0c;在信息建设国产化中有着举足轻重的地位。 过去几十年&a…

虚函数求圆形、矩形面积

目录 题目 源码 结果示例 题目 写一个程序&#xff0c;定义抽象基类Shape&#xff0c;由它派生出2个派生类&#xff1a;Circle(圆形)、Rectangle(矩形)&#xff0c;用一个普通函数printarea分别输出以上二者的面积&#xff0c;2个图形的数据在定义对象时给定。 源码 #inc…

软考-系统集成项目管理中级--项目质量管理(输入输出很重要!!!本章占分较高,着重复习)

本章历年考题分值统计 本章重点常考知识点汇总清单 5、成本效益分析法:对每个质量活动进行成本效益分析&#xff0c;就是要比较其可能的成本与预期的效益。达到质量要求的主要效益包括减少返工、提高生产率、降低成本、提升干系人满意度及提升赢利能力。(掌握)17下64考题 本章…

【Flutter】GetX状态管理及路由管理用法

目录 一、安装二、使用1.安装GetX插件&#xff0c;快捷生成模版代码2.主入口MaterialApp改成GetMaterialApp3.定义路由常量RoutePath类、别名映射页面RoutePages类4. 初始initialRoute&#xff0c;getPages。5.调用 总结 一、安装 dependencies: get: ^4.6.6二、使用 1.安装G…

Java八股文4

Linux篇 1.free命令-查看内存状态 free命令用于显示内存状态&#xff0c;它可以提供关于系统内存使用情况的详细信息。这个命令会显示出内存的使用情况&#xff0c;包括实体内存、虚拟的交换文件内存、共享内存区段&#xff0c;以及系统核心使用的缓冲区等。 其中&#xff0c;参…

2024年国内USB Type-C厂商的机遇与挑战分析

USB Type-C接口作为一种全新的连接标准&#xff0c;已经在各种电子设备中得到了广泛的应用。2024年&#xff0c;国内USB Type-C厂商将面临着诸多机遇和挑战&#xff0c;需要全面分析和应对&#xff0c;以确保在竞争激烈的市场中保持竞争力和持续增长。 USB TYPE-C厂商在2024年…

09-ARM开发板的HelloWorld

在ARM开发板上运行x86_64平台程序 前面在Ubuntu系统编译生成了X86_64平台的HelloWorld程序&#xff0c;通过NFS服务器&#xff0c;尝试在开发板上直接运行。 如图所示&#xff0c;程序无法正常运行&#xff0c;终端提示ARM开发板在执行x86架构&#xff08;Intel或AMD&#xff…

【Linux】地址空间虚拟地址

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 虚拟地址1.1 虚拟地址引入1.2 虚拟地址理解1.3 虚拟地址细节问题 2. 地址空间2.1 理解地址空间2.2 页表和写时拷贝 3. 进程调度 1. 虚拟地址 1.1 虚拟地址引入 先先来一个测试代码&#xff1a; 1 #include<st…

Grass注册不了、按钮灰色的解决方案

近期相信grass挂机项目不少人有所有接触。还有不了解这个项目的可以看看博客&#xff1a; http://t.csdnimg.cn/bI4UO 但是不少人注册时遇到无法注册的问题&#xff0c;或者是注册按钮显示灰色&#xff0c;放上鼠标时显示禁止。这也是博主在尝试时遇到的问题。 经过探索&…

如何解决python安装mysqlclient失败问题

在使用Django等框架来操作MySQL时&#xff0c;实际上底层还是通过Python来操作的&#xff0c;首先需要安装一个驱动程序&#xff0c;在Python3中&#xff0c;驱动程序有多种选择&#xff0c;比如有pymysql以及mysqlclient等。使用pip命令安装mysqlclient失败应如何解决&#xf…

【Linux实践室】Linux高级用户管理实战指南:Linux用户与用户组编辑操作详解

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;Linux查看用户属性命令2.1.1 &#x1f47b;…

测试用例的编写评审

1、什么叫软件测试用例 什么是测试用例 测试用例(TestCase) 是为项目需求而编制的一组测试输入、执行条件 以及预期结果&#xff0c;以便测试某个程序是否满足客户需求。–测试依据 可以总结为:每一个测试点的数据设计和步骤设计。–测试用例 2、测试用例的重要性(了解) 2.1…

社媒矩阵运营解决方案:海外云手机

在全球化的浪潮下&#xff0c;企业愈发认识到通过海外社交媒体平台扩大影响力、树立品牌形象及抢占国际市场的巨大机遇。因此&#xff0c;运营海外社交媒体账户已逐渐成为企业战略部署的重要组成部分。为了全面捕捉多渠道的流量&#xff0c;众多企业选择同时运营多个平台的多个…

基于Spring Boot的校园招聘系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

基于SkyEye运行Qt:著名应用程序开发框架

Qt是一个著名的跨平台的C图形用户界面应用程序开发框架&#xff0c;目前包括Qt Creator、Qt Designer等等快速开发工具&#xff0c;还支持2D/3D图形渲染、OpenGL&#xff0c;允许真正的组件编程&#xff0c;是与GTK、MFC、OWL、ATL一样的图形界面库。使用Qt开发的软件可以做到一…

抖音直播间没流量怎么办?如何快速提升直播间人气?

抖音直播间人气低迷&#xff0c;是否因为投入的资金不足或是数据表现不够抢眼而让你感到困惑&#xff1f;要提升抖音直播间的人气&#xff0c;首先需要深入了解抖音的推荐逻辑&#xff0c;探究直播间人气的真正来源。 抖音直播间的人气来源有哪些&#xff1f; 抖音直播间人气…

SpringMVC核心流程解析

SpringMVC核心流程解析 DispatcherServlet的继承关系请求流程分析获取HandlerChain(ControllrtMethod拦截器)获取HandlerAdapter handlerMappings的初始化过程 DispatcherServlet的继承关系 DispatcherServlet本质是一个servlet&#xff0c;既然是servlet&#xff0c;一个请求…

Pytorch-自动微分模块

&#x1f947;接下来我们进入到Pytorch的自动微分模块torch.autograd~ 自动微分模块是PyTorch中用于实现张量自动求导的模块。PyTorch通过torch.autograd模块提供了自动微分的功能&#xff0c;这对于深度学习和优化问题至关重要&#xff0c;因为它可以自动计算梯度&#xff0c…

视觉位置识别与多模态导航规划

前言 机器人感知决策是机器人移动的前提&#xff0c;机器人需要对周围环境实现理解&#xff0c;而周围环境通常由静态环境与动态环境构成。机器人在初始状态或者重启时需要确定当前所处的位置&#xff0c;然后根据用户的指令或意图&#xff0c;开展相应移动或抓取操作。通过视觉…