设计模式之建造者模式(C++实现)

更多设计模式参看: 设计模式之模式概述(模式汇总)(C++实现)

介绍

建造者模式是较为复杂的创建型模式,它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。

意图:

建造者模式(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)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),饮料(Drink)可以是可口可乐(coke)或百事可乐(pepsi)或者咖啡(cafe),小吃(Snacks)可以是炸薯条(French fries)或 洋葱圈(Onion rings)

GitHub

BuilderPattern

产品角色(Product)

/// 产品角色(Product)
class ProductMeal {
public:
    ProductMeal() {
        std::cout << "ProductMeal Hello" << std::endl;
    };
    ~ProductMeal() {
        std::cout << "ProductMeal Bye" << 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 << "Burger is " << mBurger << std::endl;
        std::cout << "Drink is " << mDrink << std::endl;
        std::cout << "Snacks is " << mSnacks << std::endl;
    }

private:
    std::string mBurger;
    std::string mDrink;
    std::string mSnacks;
};

抽象建造者(AbstractBuilder)

/// 抽象建造者(AbstractBuilder)
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;

};

具体建造者(ConcreteBuilder)

/// 具体建造者(ConcreteBuilder)
class ConcreteBuilderMeal_A : public AbstractBuilder{ /// 套餐A
public:
    ConcreteBuilderMeal_A(){
        std::cout << "ConcreteBuilderMeal_A Hello" << std::endl;
        meal = new ProductMeal();
    }
    ~ConcreteBuilderMeal_A() override{
        std::cout << "ConcreteBuilderMeal_A Bye" << std::endl;
        delete meal;
    }
    void buildBurger() override {
        meal->setBurger("Veg Burger");
    };
    void buildDrink() override {
        meal->setDrink("coke");
    }
    void buildSnacks() override {
        meal->setSnacks("French fries");
    }
    ProductMeal* getMeal() override {
        return meal;
    }
private:
    ProductMeal *meal;
};

class ConcreteBuilderMeal_B : public AbstractBuilder{ /// 套餐B
public:
    ConcreteBuilderMeal_B(){
        std::cout << "ConcreteBuilderMeal_B Hello" << std::endl;
        meal = new ProductMeal();
    }
    ~ConcreteBuilderMeal_B() override{
        std::cout << "ConcreteBuilderMeal_B Bye" << std::endl;
        delete meal;
    }
    void buildBurger() override {
        meal->setBurger("Chicken Burger");
    };
    void buildDrink() override {
        meal->setDrink("pepsi");
    }
    void buildSnacks() override {
        meal->setSnacks("Onion rings");
    }
    ProductMeal* getMeal() override {
        return meal;
    }
private:
    ProductMeal *meal;
};
class ConcreteBuilderMeal_C : public AbstractBuilder{ /// 套餐C
public:
    ConcreteBuilderMeal_C(){
        std::cout << "ConcreteBuilderMeal_C Hello" << std::endl;
        meal = new ProductMeal();
    }
    ~ConcreteBuilderMeal_C() override{
        std::cout << "ConcreteBuilderMeal_C Bye" << std::endl;
        delete meal;
    }
    void buildBurger() override {
        meal->setBurger("Veg Burger");
    };
    void buildDrink() override {
        meal->setDrink("cafe");
    }
    void buildSnacks() override {
        meal->setSnacks("French fries");
    }
    ProductMeal* getMeal() override {
        return meal;
    }
private:
    ProductMeal *meal;
};

指挥者(Director)

/// 指挥者(Director)
class Director
{
public:
    Director() {
        std::cout << "Director Hello" << std::endl;
    };
    ~Director() {
        std::cout << "Director Bye" << 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() {

    //指挥者
    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;
    //指定具体建造者C
    builder = new ConcreteBuilderMeal_C();
    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;

    getchar();
    return 0;
}

输出

在这里插入图片描述

建造者模式VS工厂模式

工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

个人能力有限,如有错误之处或者其他建议,敬请告知欢迎探讨,谢谢!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
建造者模式是一种创建型设计模式,它允许您创建不同类型的对象,而无需暴露对象的创建逻辑。它将对象的构建步骤分解为可重用的部分,并允许您按顺序执行它们。这使得您能够创建具有不同属性的对象,而无需编写大量的重复代码。 在建造者模式中,有一个建造者类,它负责创建对象的特定部分,如电脑的CPU、内存和硬盘等。该类具有一个公共接口,该接口定义了每个部分的构建步骤。在构建步骤完成后,该类可以返回一个完整的对象。 建造者模式也包括一个指导者类,它负责调用建造者类的构建步骤,并按照正确的顺序执行它们。指导者类知道如何创建对象,但不知道如何创建对象的每个部分,因此它将这个工作委托给建造者类。 以下是一个简单的C++实现建造者模式的示例代码: ```cpp #include <iostream> #include <string> class Computer { public: void setCPU(const std::string& cpu) { m_cpu = cpu; } void setMemory(const std::string& memory) { m_memory = memory; } void setHardDisk(const std::string& hardDisk) { m_hardDisk = hardDisk; } void show() { std::cout << "CPU: " << m_cpu << std::endl; std::cout << "Memory: " << m_memory << std::endl; std::cout << "Hard Disk: " << m_hardDisk << std::endl; } private: std::string m_cpu; std::string m_memory; std::string m_hardDisk; }; class Builder { public: virtual ~Builder() {} virtual void buildCPU() = 0; virtual void buildMemory() = 0; virtual void buildHardDisk() = 0; virtual Computer* getResult() = 0; }; class Director { public: void setBuilder(Builder* builder) { m_builder = builder; } void construct() { m_builder->buildCPU(); m_builder->buildMemory(); m_builder->buildHardDisk(); } private: Builder* m_builder; }; class DesktopBuilder : public Builder { public: DesktopBuilder() { m_computer = new Computer; } ~DesktopBuilder() { delete m_computer; } void buildCPU() { m_computer->setCPU("Intel Core i7"); } void buildMemory() { m_computer->setMemory("16GB DDR4 RAM"); } void buildHardDisk() { m_computer->setHardDisk("2TB SATA Hard Disk"); } Computer* getResult() { return m_computer; } private: Computer* m_computer; }; int main() { Director director; DesktopBuilder desktopBuilder; director.setBuilder(&desktopBuilder); director.construct(); Computer* computer = desktopBuilder.getResult(); computer->show(); return 0; } ``` 在这个示例中,我们创建了一个Computer类,它有三个成员变量:CPU、内存和硬盘。我们还创建了一个Builder类,它定义了创建Computer对象的构建步骤,并且为每个部分提供了一个抽象接口。我们还创建了一个Director类,它负责调用建造者类的构建步骤,并按照正确的顺序执行它们。 在具体的建造者实现中,我们创建了一个DesktopBuilder类,它实现了Builder接口,并具有一个Computer成员变量。在DesktopBuilder类的构建步骤中,我们设置了Computer对象的CPU、内存和硬盘。最后,我们返回一个完整的Computer对象。 在main函数中,我们创建了一个Director对象,并将DesktopBuilder对象传递给setBuilder函数。然后我们调用construct函数,它将调用DesktopBuilder的构建步骤,并返回一个完整的Computer对象。我们最后打印出这个对象的属性,以验证它是否被正确构建。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值