C++设计模式-建造者模式 原创 设计模式 2021年10月18日 20:55 夏至未至 1313 当前内容 7774 字,在路上,马上到,马上到 ### 目录 [TOC] ### 建造者模式介绍 #### 什么是建造者模式 建造者模式是较为复杂的创建型模式,`它将客户端与对象的创建过程分离`(这个对象很复杂,可能包含多个组件),客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。 #### 为何使用建造者模式 建造者模式(Builder Pattern): 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。 #### 模式核心 将变与不变分离开。 #### 何时使用建造者模式 (1) 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。 (2) 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。 (3) 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。 (4) 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。 ### 使用场景 #### 生活中场景 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 #### 软件中场景 JAVA 中的 StringBuilder。 ### 模式特点 #### 优点 (1) 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。 (2) 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。 (3) 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。 #### 缺点 (1) 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。 (2) 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。 ### 模式角色类 - 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。 - 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。 - 产品角色(Product):被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。 - 指挥者(Director): 指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。 ### 实操代码 #### 场景 使用建造者模式生成不同快餐套餐。 一个典型的套餐可以由以下部分组成: 一个汉堡(Burger)、一杯饮料( Drink)和一份小吃(Snacks)。 其中: - 汉堡(Burger)可以是牛肉汉堡、鸡肉汉堡、猪肉汉堡 - 饮料(Drink)可以是可乐、矿泉水、哇哈哈 - 小吃(Snacks)可以是水饺、方便面、土豆片 #### 上机代码 #include #include // 产品角色(一个套餐) class ProductMeal { public: ProductMeal() { std::cout << "一个套餐被创建" << std::endl; }; ~ProductMeal() { std::cout << "一个套餐被销毁" << std::endl; }; void setBurger(const std::string& iburger) { mBurger = iburger; } void setDrink(const std::string& idrink) { mDrink = idrink; } void setSnacks(const std::string& isnacks) { mSnacks = isnacks; } void showMeal() { std::cout << "汉堡 " << mBurger << std::endl; std::cout << "饮料 " << mDrink << std::endl; std::cout << "小吃 " << mSnacks << std::endl; } private: std::string mBurger; std::string mDrink; std::string mSnacks; }; // 抽象建造者 class AbstractBuilder { public: virtual ~AbstractBuilder() = default; //抽象方法: // 创建汉堡 virtual void buildBurger() = 0; // 创建饮料 virtual void buildDrink() = 0; // 创建小吃 virtual void buildSnacks() = 0; // 获取这个套餐 virtual ProductMeal* getMeal() = 0; protected: AbstractBuilder() = default; }; // 具体建造者(套餐A) class ConcreteBuilderMeal_A : public AbstractBuilder { public: ConcreteBuilderMeal_A() { std::cout << "套餐A被创建" << std::endl; meal = new ProductMeal(); } ~ConcreteBuilderMeal_A() override { std::cout << "套餐A被销毁" << std::endl; delete meal; } void buildBurger() override { meal->setBurger("牛肉汉堡"); }; void buildDrink() override { meal->setDrink("可乐"); } void buildSnacks() override { meal->setSnacks("水饺"); } ProductMeal* getMeal() override { return meal; } private: ProductMeal* meal; }; // 套餐B class ConcreteBuilderMeal_B : public AbstractBuilder { public: ConcreteBuilderMeal_B() { std::cout << "套餐B被创建" << std::endl; meal = new ProductMeal(); } ~ConcreteBuilderMeal_B() override { std::cout << "套餐B被销毁" << std::endl; delete meal; } void buildBurger() override { meal->setBurger("鸡肉汉堡"); } void buildDrink() override { meal->setDrink("矿泉水"); } void buildSnacks() override { meal->setSnacks("方便面"); } ProductMeal* getMeal() override { return meal; } private: ProductMeal* meal; }; // 套餐C class ConcreteBuilderMeal_C : public AbstractBuilder { public: ConcreteBuilderMeal_C() { std::cout << "套餐C被创建" << std::endl; meal = new ProductMeal(); } ~ConcreteBuilderMeal_C() override { std::cout << "套餐C被销毁" << std::endl; delete meal; } void buildBurger() override { meal->setBurger("猪肉汉堡"); } void buildDrink() override { meal->setDrink("哇哈哈"); } void buildSnacks() override { meal->setSnacks("土豆片"); } ProductMeal* getMeal() override { return meal; } private: ProductMeal* meal; }; // 指挥者 class Director { public: Director() { std::cout << "指挥者被创建" << std::endl; }; ~Director() { std::cout << "指挥者被销毁" << std::endl; } // 不同建造者制作不同套餐 void setBuilder(AbstractBuilder* iBuilder) { this->builder = iBuilder; } //封装组装流程,返回建造结果 ProductMeal* construct() { assert(builder != nullptr); builder->buildBurger(); builder->buildDrink(); builder->buildSnacks(); return builder->getMeal(); } private: AbstractBuilder* builder = nullptr; }; // 测试 int main() { std::cout << "网站:https://www.codecomeon.com/" << std::endl; std::cout << std::endl; //指挥者 Director director; //抽象建造者 AbstractBuilder* builder; //产品:套餐 ProductMeal* meal; //指定具体建造者A builder = new ConcreteBuilderMeal_A(); director.setBuilder(builder); meal = director.construct(); meal->showMeal(); delete builder; std::cout << "======================" << std::endl; //指定具体建造者B builder = new ConcreteBuilderMeal_B(); director.setBuilder(builder); meal = director.construct(); meal->showMeal(); delete builder; std::cout << "======================" << std::endl; //指定具体建造者C builder = new ConcreteBuilderMeal_C(); director.setBuilder(builder); meal = director.construct(); meal->showMeal(); delete builder; getchar(); return 0; } #### 执行输出 网站:https://www.codecomeon.com/ 指挥者被创建 套餐A被创建 一个套餐被创建 汉堡 牛肉汉堡 饮料 可乐 小吃 水饺 套餐A被销毁 一个套餐被销毁 ====================== 套餐B被创建 一个套餐被创建 汉堡 鸡肉汉堡 饮料 矿泉水 小吃 方便面 套餐B被销毁 一个套餐被销毁 ====================== 套餐C被创建 一个套餐被创建 汉堡 猪肉汉堡 饮料 哇哈哈 小吃 土豆片 套餐C被销毁 一个套餐被销毁 ### 建造者模式与工厂模式 工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。 本文标题: C++设计模式-建造者模式 本文作者: 夏至未至 发布时间: 2021年10月18日 20:55 最近更新: 2022年2月9日 12:08 原文链接: 许可协议: 署名-非商业性-禁止演绎 4.0 国际(CC BY-NC-ND 4.0) 请按协议转载并保留原文链接及作者 设计模式(25) 上一个 C++设计模式-适配器模式 下一个 C++设计模式-原型模式 当前文章评论暂未开放,请移步至留言处留言。