AI Chat 设计模式:4. 建造者模式

本文是该系列的第四篇,采用问答式的方式展开,问题由我提出,答案由 Chat AI 作出,灰色背景的文字则主要是我的旁白与思考。

问题列表

  • Q.1 说说建造者模式
  • A.1
  • Q.2 “将一个复杂对象的构建过程和其表示分离”,这里不是很清楚,给我讲解一下吧
  • A.2
  • Q.3 给我举一个建造者模式的例子吧
  • A.3
  • Q.4 你的代码里,客户是通过 builderA 和 builderB 来获取汽车,似乎不太好呢
  • A.4
  • Q.5 客户端是应该通过建造者获取产品还是通过指挥者类来获取产品呢?
  • A.5
  • Q.6 我是想问 “getCar这个方法应该由客户端调用,还是由指挥者类来调用”
  • A.6
  • Q.7 复杂的产品,必须要继承自同一个产品基类吗?
  • A.7
  • Q.8 画类图
  • A.7

Q.1 说说建造者模式

A.1

建造者模式是一种创建型设计模式,它将一个复杂对象的构建过程和其表示分离,使得同样的构建过程可以创建不同的表示。这个模式的核心思想是将一个复杂的对象构建过程拆分成多个步骤,在这些步骤之间建立一定的依赖关系,最终生成一个完整的对象。

建造者模式通常包含以下几个角色:

  1. Builder(建造者):定义用于构建复杂对象的接口,包含多个抽象方法,每个方法对应一个构建步骤。

  2. ConcreteBuilder(具体建造者):实现 Builder 接口,完成复杂对象的各个构建步骤,最终生成一个合成对象。同时具有访问和获取构建结果的方法

  3. Director(指挥者):负责组合 Builder 中的各个构建步骤,最终得到复杂对象。它不直接创建对象,而是通过调用Builder的方法得到一个构建过程的完整对象。

  4. Product(产品):产品是由具体建造者生产的复杂对象,它包含了多个部件,具有一定的复杂性和功能性。

使用建造者模式可以有效地将对象的创建过程模块化,降低了复杂对象的构建难度,提高了可维护性和可扩展性。

Q.2 “将一个复杂对象的构建过程和其表示分离”,这里不是很清楚,给我讲解一下吧

A.2

当我们需要构建一个复杂对象时,可能需要通过多个步骤来完成这个过程,包括创建多个部分、添加属性、设置关联等等,这些步骤的执行顺序和具体实现可能因对象类型、使用场景等因素而不同。此时,如果将这个复杂的构建过程和最终对象的表示紧密耦合在一起,将会导致代码复杂、难以维护。

建造者模式的核心思想就是将这个复杂的构建过程和最终对象的表示分离开来,把构建复杂对象的过程拆分成一些简单的步骤,这些步骤之间不直接关联,而是在指挥者的统筹下依次调用各个步骤,最终生成构建完成的对象。

通过这种方式,建造者模式实现了构建过程和表示之间的松耦合,使得我们可以根据需要构建不同的对象,而且能够更加灵活地对构建过程进行扩展或者重构,同时也提高了代码的可读性和可维护性。

表示:其实就是我们想要产生的最终对象,也就是 Product 类对象;
构建:Builder 类就是对象的构建;
构建过程:是指 Director 类中产品构建步骤的装配顺序,该过程是稳定不会变化的。只要传递给指挥者类不同的具体建造者(ConcreteBuilder)子类,它就能构建出不同的产品(Product)。
下面举一个例子来说明。

Q.3 给我举一个建造者模式的例子吧

A.3

假设我们要创建一个汽车类,这个汽车类包含多个部件(例如车架、发动机、轮胎、油箱等等),并且每个部件的属性、数量和顺序都有所不同。

我们可以使用建造者模式来构建这个复杂对象。以下是一个简单的示例代码:

#include <iostream>
#include <string>
using namespace std;//定义汽车类
class Car {
public://车架string frame;//发动机string engine;//轮胎string tire;//油箱string tank;//车辆信息打印函数void printCarInfo() {cout << "Car Info: " << endl;cout << "Frame: " << frame << endl;cout << "Engine: " << engine << endl;cout << "Tire: " << tire << endl;cout << "Tank: " << tank << endl;}
};//定义汽车建造者类
class CarBuilder {
public://构造函数CarBuilder() : m_car(new Car) {}//设置车架virtual void setFrame() {}//设置发动机virtual void setEngine() {}//设置轮胎virtual void setTire() {}//设置油箱virtual void setTank() {}//获取构造完成的车辆Car* getCar() {return m_car;}protected://保存构造完成的车辆Car* m_car;
};//定义汽车建造者A
class CarBuilderA : public CarBuilder {
public://设置车架void setFrame() {m_car->frame = "Frame A";}//设置发动机void setEngine() {m_car->engine = "Engine A";}//设置轮胎void setTire() {m_car->tire = "Tire A";}//设置油箱void setTank() {m_car->tank = "Tank A";}
};//定义汽车建造者B
class CarBuilderB : public CarBuilder {
public://设置车架void setFrame() {m_car->frame = "Frame B";}//设置发动机void setEngine() {m_car->engine = "Engine B";}//设置轮胎void setTire() {m_car->tire = "Tire B";}//设置油箱void setTank() {m_car->tank = "Tank B";}
};//定义指挥者类
class Director {
public:void constructCar(CarBuilder* builder) {builder->setFrame();builder->setEngine();builder->setTire();builder->setTank();}
};//主函数
int main() {CarBuilderA builderA;CarBuilderB builderB;Director director;//指挥者指定汽车建造者A来构建汽车director.constructCar(&builderA);Car* carA = builderA.getCar();carA->printCarInfo();//指挥者指定汽车建造者B来构建汽车director.constructCar(&builderB);Car* carB = builderB.getCar();carB->printCarInfo();return 0;
}

在代码中,Car类是我们所要构建的复杂对象。CarBuilder是汽车建造者的接口类,包含了构建汽车的各种方法。不同的汽车建造者继承这个接口类,并完成各自的构建过程,即不同的车架、发动机、轮胎和油箱Director类是指挥者,负责组合不同步骤的构建者来生成最终的复杂对象加粗样式

最后,我们可以使用CarBuilderACarBuilderB来构建不同的汽车对象。

这个例子还是比较好理解的,对各个类的作用也进行了讲解。
一般来说,指挥者类组合一个 builder 类的对象,同时提供一个接口让客户端来设置不同的builder具体对象。但像例子中这样不直接持有也是可以的,在使用的时候直接传入即可。
我们注意到,在 main() 函数(客户端)中,是通过 buildA、buildB 这个两个具体建造者类对象来获取产品的。这点我并不认可,因为这个例子明显是一个标准的建造者模式示例,拥有指挥者类,不应该让客户端继续与建造者类沟通。

Q.4 你的代码里,客户是通过 builderA 和 builderB 来获取汽车,似乎不太好呢

A.4

非常抱歉,我的代码确实有误,我在获取汽车对象那一段没有更新。在正确的代码中,我们应该将指挥者和具体的汽车建造者进行配合,完成具体的构建过程,最终返回构建完成的汽车对象

以下是代码的修改版本:

#include <iostream>
#include <string>
using namespace std;//定义汽车类
class Car {
public://车架string frame;//发动机string engine;//轮胎string tire;//油箱string tank;//车辆信息打印函数void printCarInfo() {cout << "Car Info: " << endl;cout << "Frame: " << frame << endl;cout << "Engine: " << engine << endl;cout << "Tire: " << tire << endl;cout << "Tank: " << tank << endl;}
};//定义汽车建造者类
class CarBuilder {
public://构造函数CarBuilder() : m_car(new Car) {}//设置车架virtual void setFrame() {}//设置发动机virtual void setEngine() {}//设置轮胎virtual void setTire() {}//设置油箱virtual void setTank() {}//获取构造完成的车辆Car* getCar() {return m_car;}protected://保存构造完成的车辆Car* m_car;
};//定义汽车建造者A
class CarBuilderA : public CarBuilder {
public://设置车架void setFrame() {m_car->frame = "Frame A";}//设置发动机void setEngine() {m_car->engine = "Engine A";}//设置轮胎void setTire() {m_car->tire = "Tire A";}//设置油箱void setTank() {m_car->tank = "Tank A";}
};//定义汽车建造者B
class CarBuilderB : public CarBuilder {
public://设置车架void setFrame() {m_car->frame = "Frame B";}//设置发动机void setEngine() {m_car->engine = "Engine B";}//设置轮胎void setTire() {m_car->tire = "Tire B";}//设置油箱void setTank() {m_car->tank = "Tank B";}
};//定义指挥者类
class Director {
public:Car* constructCar(CarBuilder* builder) {builder->setFrame();builder->setEngine();builder->setTire();builder->setTank();return builder->getCar();}
};//主函数
int main() {CarBuilderA builderA;CarBuilderB builderB;Director director;//指挥者指定汽车建造者A来构建汽车Car* carA = director.constructCar(&builderA);carA->printCarInfo();//指挥者指定汽车建造者B来构建汽车Car* carB = director.constructCar(&builderB);carB->printCarInfo();return 0;
}

在新的代码中,Director类的constructCar函数接受一个CarBuilder指针参数,用于在执行构建过程并返回构建成功的汽车对象。客户端代码现在可以通过Director来调用不同的CarBuilder来获得不同类型的汽车对象了。

既然分离出了指挥者类,就应该通过指挥者类来获取最终表示,而不应该让客户端继续调用建造者类。当然,如果,没有分离出指挥者类,那自然是没任何问题的,此处不再展开。
为了确定,AI 不是屈服于我作出的违心答案,我还将继续追问这一点。

Q.5 客户端是应该通过建造者获取产品还是通过指挥者类来获取产品呢?

A.5

客户端应该通过指挥者类来获取产品,而不是直接通过建造者获取产品。

指挥者类的作用是协调建造者中的各个构建步骤,确保整个构建过程的正确执行。客户端如果直接通过建造者来获取产品,那么就需要了解建造者的具体实现细节,带来了一定的耦合性,同时也不利于后期的维护和扩展。

通过指挥者类来获取产品,客户端只需要与指挥者类进行交互,即使建造者的实现发生了改变,也不会对客户端造成影响。同时,指挥者类也可以封装建造者构建对象的过程,提供更加方便的接口给客户端使用。

我感觉它这里回答的有问题,尤其是斜体字部分,或许它没有理解我的问题。客户端即使通过建造者类来获取产品,也不需要了解具体实现细节,只是调用 getCar() 接口而已。因此,建造者的实现发生了改变,对客户端的调用也不会有任何影响。
这就是 AI 一本正经的胡说八道吧。

Q.6 我是想问 “getCar这个方法应该由客户端调用,还是由指挥者类来调用”

A.6

getCar 方法应该由指挥者类来调用,这也是指挥者类的作用的一部分。

由于指挥者类负责协调建造者的构建步骤,最终将构建完成的产品组装起来,因此在 constructCar 方法中应该调用建造者的各个构建方法,并在完成构建之后,从建造者对象中获取构建完成的产品。指挥者类可以把获得的产品返回给客户端,或者进一步处理之后返回。因此,在 constructCar 方法中的返回值就是通过建造者构建好的产品。

对于客户端调用建造者的 getCar 方法来获得产品,会暴露建造的过程细节,这样会导致建造者与客户端之间的紧耦合。

现在它算是明确回答了我的问题,应该让指挥者类来返回成品,别让客户端再调用 getCar() 方法了。但“会暴露建造的过程细节”我是不完全认同的,也就是多暴露一个 getCar() 方法罢了,还称不上实现细节,耦合确实加重了。

Q.7 复杂的产品,必须要继承自同一个产品基类吗?

A.7

在建造者模式中,复杂的产品并不一定必须继承自同一个产品基类建造者模式关注的是构建过程和组装复杂对象,而不是具体的产品类型

建造者模式允许构建不同类型的产品,这些产品可以是无关的、不具备共同特征的。如果产品之间没有共同的属性或行为,那么它们可以是独立的类,而不需要继承自同一个基类。

然而,如果多个产品类型具有一些共同的属性或行为,使用继承来实现一个产品基类是合理的。通过继承,可以提取和共享共同的代码,简化代码结构,同时也方便对产品进行统一管理和扩展。

继承产品基类有利于实现多态,使得客户端可以以统一的方式操作不同类型的产品。此外,基类也可以定义一些虚拟方法,供子类进行自定义实现。

所以,是否需要继承自同一个产品基类取决于具体的设计需求和产品结构,根据实际情况来决定。

关注的不是产品类型,而是产品的构建步骤,只要有相同的构建步骤,就可以使用建造者模式。

Q.8 画类图

A.7

要记住:并不要求创建的产品继承自同一个基类,只是我们这个例子恰好如此。

在这里插入图片描述

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

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

相关文章

九龙证券|利好政策密集发布,机构扎堆看好的高增长公司曝光

新能源轿车销量和保有量快速增长&#xff0c;带来了充电桩商场的微弱需求。 日前&#xff0c;商务部部长王文涛表明&#xff0c;本年将在落实好方针的一起&#xff0c;活跃出台新方针办法&#xff0c;比方辅导当地展开新能源轿车下乡活动&#xff0c;优化充电等使用环境&#x…

用post man 上传图片到微信

用post man 上传图片到微信 记录一下 我目前完成的小程序后端开发过程 这里用post man 做测试上传客服群的qrcode 有在网路上搜寻了一下发现都没有相关的教学可能是太简单了 但我相信还是会有人用的到的 不多说直接来吧 1.参考文档 https://developers.weixin.qq.com/minipro…

75岁母亲被6个子女遗弃身亡,“凶手”一句话惹怒全网:当你老了,真相比想象中更残忍

看到一个让人唏嘘的新闻。 江西上饶&#xff0c;一名老人被发现在竹林中去世。 没人能想到&#xff0c;导致老人死亡的“凶手”&#xff0c;会是她的亲生儿女。 老人陈阿婆一生有过三次婚姻&#xff0c;共育有6个子女。 第二次婚姻结束后&#xff0c;她带着9岁的儿子黄某改嫁&a…

教育孩儿子要懂的心理学

ISBN : 978-7-5472-5944-3 作者 : 万莹 页数 : 243页 阅读时间 : 2021-09-01 推荐指数 : ★★★★☆ &#xff02;孩子的世界&#xff0c;与成人的截然不同&#xff0c;倘不先行理解&#xff0c;一味蛮做&#xff0c;便大碍于孩子的发达&#xff0e;&#xff02;&#xff0d;&a…

《亲爱的小孩》里三位母亲的靠谱与不靠谱

平时看电视剧不多&#xff0c;这些天难得有些空闲&#xff0c;听说有部电视剧在贩卖焦虑&#xff0c;这勾起了我的好奇心&#xff0c;一查这剧竟然汇集了我喜爱的好几位实力派演员&#xff0c;于是就追起了这部《亲爱的小孩》。 看了几集&#xff0c;没有感觉到电视剧故意在贩卖…

为年迈母亲打造的“亲情关怀”视频聊天软件

写在前面 母亲的眼神越来越不好了&#xff0c;长期干农活的手也愈加粗糙&#xff0c;智能手机本是一个平常之物&#xff0c;她确无缘使用&#xff0c;现在仍在不断更换着“翻盖手机”。为了能让她绕开微信视频聊天那些繁琐而容易点错的功能&#xff0c;程序员的我“开发”下面…

情感脑机接口与跨被试情感模型问题研究

情感脑机接口与跨被试情感模型问题研究 基于最大分类器差异域对抗方法的跨被试脑电情绪识别研究引言部分关键要点提取MCD_DA 模型解读数据集创建以及处理模型训练步骤实验结果 Multisource Transfer Learning for Cross-Subject EEG Emotion RecognitionRELATED WORKMETHODSSou…

妈妈的情绪,决定孩儿子的未来

ISBN&#xff1a;978-7-5472-5951-1 页数&#xff1a;247页 作者&#xff1a;融智 阅读时间&#xff1a;2021-08-08 推荐指数&#xff1a;★★★★☆ 妈妈可能不是天才&#xff0c;但是可以成为天才的母亲。 过度慈爱会败子&#xff0c;过度严厉也会毁子。 父母真正的爱就是越…

2步就能完成的情感分析模型

ABSA&#xff08;Aspect Based Sentiment Analysis&#xff09;是一种在给定的语料库中同时提取&#xff08;co-extracting &#xff09;表达意见和&#xff08;事物&#xff09;属性/方面术语&#xff08;意见目标&#xff09;以及它们之间的关系的任务。 方面级情感分类是情…

家庭教育中有近一半是由母亲负责孩子学习,占49%,父亲负责仅占10%

近年来&#xff0c;随着国家经济的高速发展&#xff0c;国民对教育的需求越来越大&#xff0c;特别是对家庭教育的重视程度越来越高。家庭是人生的第一所学校&#xff0c;家长是孩子的第一任老师&#xff0c;要给孩子讲好“人生第一课”&#xff0c;帮助扣好人生第一粒扣子。 …

案例研究 | 运用设计冲刺,解决俄罗斯家庭暴力问题

问题 家庭暴力是一个困扰全球的问题&#xff0c;运用设计冲刺能帮我们解决它吗&#xff1f; 在俄罗斯&#xff0c;每5名妇女就有1名遭受到丈夫或伴侣的虐待&#xff0c;而这种情况在2017年国家将家庭虐待定为非刑事罪后更是急剧恶化。 于是&#xff0c;俄罗斯的一个律师和新闻…

母亲节营销案例大盘点,真的有被狠狠共情住

⼀直以来&#xff0c;节⽇营销都是品牌借势和消费者建⽴情感链接的好时机。尤其是在母亲节这个温情的⽇⼦⾥&#xff0c;借助催泪、温情的⼴告歌颂母爱的无私与伟⼤来打动消费&#xff0c;也成为品牌母亲节营销的标配。 随之⽽来的&#xff0c;越来越多的品牌也⾯临困局&#x…

酒店评论情感分析,亲妈级教程

酒店评论情感分析&#xff0c;采集与分词篇 开篇吐槽一下下。 类似携程这种生活类网站&#xff0c;还有电商类网站&#xff0c;不是驻守被爬的城墙内就是在反爬的道路上行走。不断的更新加密&#xff0c;批量化的采集不断破解并升级程式&#xff0c;并在网络之上布施教程&…

用孕妇的思维和孕妇对话——《用孩子的思维和孩子对话》

看惯了某鱼上经典的卖货话术&#xff0c;“不懂事怀孕了&#xff0c;遂出”。没想到我居然也快要当爸爸了。这几个月准爸爸的生活让我切身的体会到了孕妇的不容易以及陪伴孕妇的辛苦。本文不打算歌颂母亲或者替准爸爸们倒苦水&#xff0c;单纯总结思考一下孕期夫妻如何沟通。加…

(含完整代码)简易Android计算器的实现

文章结构 1、项目要求2、实现思路3、代码实现主文件子文件 4、效果预览 1、项目要求 其实老师的要求就是做一个简易的计算器&#xff0c;有两个文本框&#xff0c;一个按钮&#xff0c;然后实现加法即可。 但是我还是想做一个比较好康的计算器&#xff08;如下&#xff09;&am…

Android——在线计算器完整代码

实现效果 一、xml布局文件 这里采用线性布局&#xff0c;关于计算器的布局&#xff0c;可以查看之前的文章。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"and…

Qt简易计算器的代码实现

大二用qt写的简易计算机&#xff0c;已经修改完bug,请放心食用 输入的时候一定用按钮&#xff0c;不要直接在文本框中输入 在qt中新建这几个文件&#xff0c;运行就OK了 main.cpp #include "calculator.h" #include <QApplication>int main(int argc, char *…

chatgpt赋能python:如何打开Python黑色界面

如何打开Python黑色界面 Python黑色界面是一个流行的Python环境编辑器。很多Python开发者首选Python黑色界面来编写和运行Python程序。但是&#xff0c;很多人还不知道如何打开Python黑色界面。在这篇文章中&#xff0c;我们将介绍如何打开Python黑色界面&#xff0c;以及一些…

【无标题】分享3款好用的简易视频剪辑软件

分享3款好用的小白视频剪辑软件 本人是个短视频爱好者&#xff0c;经常需要剪辑视频&#xff0c;在实际操作中发现&#xff0c;那些专业的视频剪辑软件操作非常复杂&#xff0c;不易操作&#xff0c;而且文件又大。那些简单的视频剪辑软件小而精巧&#xff0c;操作方便&#xf…

怎么剪切视频中的一部分?不如试试这个软件

怎么剪切视频中的一部分&#xff1f;我们在进行视频剪辑的时候&#xff0c;需要导入大量的素材&#xff0c;我们不可能完整的保留整段素材。通常情况下&#xff0c;我们需要对已有的素材进行编辑分割。这里小编就来给大家介绍在电脑上对视频进行分割的方法。 怎么剪切视频中的一…