编程语言
首页 > 编程语言> > C++ 设计模式 建造者模式(复杂对象的构建与其表示分离)肯德基不同烧鸡的制作过程

C++ 设计模式 建造者模式(复杂对象的构建与其表示分离)肯德基不同烧鸡的制作过程

作者:互联网

文章目录


思考:
为何肯德基麦当劳这些快餐能在中国这个上下五千年的国都站住脚? 中国的鱼香肉丝为何不能成为令人追捧的快餐?
因为麦当劳肯德基使用的是统一制造的快餐, 也就相当于厨师是一个厨师, 而中国的饭店每个都有鱼香肉丝, 但是中国的饭店每个店的厨师都不相同, 鱼香肉丝的味道也各不相同, 正是因为这样的差别, 我们不确定未吃过的店里面的鱼香肉丝是否使我们想吃的, 而肯德基我们不管在哪家店, 吃的汉堡都是一个味道的, 只要喜欢吃, 任意哪家的都可以吃;
因此鱼香肉丝依赖于厨师, 想想设计模式的原则?
依赖倒转原则: 抽象不应该依赖细节, 但是细节应该依赖抽象, 这样做的结果就是很被动; 而肯德基可以的工作流程相当于抽象流程(放料,烧烤,摸辣等), 具体放什么配料, 烤多长时间等细节都是依赖于这个抽象;

本文还涉及到两个知识点

class A{
public: 
    virtual ~A(){} // 命令1
    virtual void getName(){};
};

class B : public A{
private:
    string name;
public:
    A * a = new A();
    B(string n): name(n){}
    ~B(){ // 如果命令1被注释掉, 这里是不会运行的
        delete a; a = nullptr;
        cout << "析构" << name <<endl;
    }
    void getName(){
        cout<< "name = "<< name <<endl;
    }
};

int main(int argc, char const *argv[])
{
    A * b1 = new B("b1");
    A * b2 = new B("b2");
    A * b3 = new B("b3");
    A * b4 = new B("b4");

    delete b1,b2,b3,b4;
    // b1->getName(); // 但这里还是可以编译成功 但是运行失败Segmentation fault (core dumped)
    b1 = nullptr;
    if(b1){
        cout << "b1 不空, 可以使用" <<endl;
        b1->getName();
    }
    cout << "这里才是正经的删除不同的指针对象" <<endl;
    delete b2, delete b3, delete b4; b2=b3=b4=nullptr;
    return 0;
}

1. 理论基础

目的:
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

主要解决:
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

何时使用:
一些基本部件不会变,而其组合经常变化的时候。

如何解决:
将变与不变分离开。

关键代码:
建造者:创建和提供实例,
导演:管理建造出来的实例的依赖关系。

应用实例:
1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。
2、JAVA 中的 StringBuilder。

优点:
1、建造者独立,易扩展。 2、便于控制细节风险。

缺点:
1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。

使用场景:
1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。

注意事项:
与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

2. 逻辑代码

在这里插入图片描述
如上图所示:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <list>
using namespace std;

// 产品类
class Product{
private:
    list<string> parts; // 使用链表创建部件
public:
    virtual ~Product(){}
    // 添加产品部件
    void Add(string part){
        parts.push_back(part);
    }

    void Show(){
        cout<< "产品创建 ... " <<endl;
        for(auto &s : parts){
            cout << s <<endl;
        }
    }
};

// Builder类
class Builder{
public:
    virtual ~Builder(){}
    virtual void BuildPartA() = 0;
    virtual void BuildPartB() = 0;
    virtual Product *GetResult() = 0;
};

// 具体建造者类
// 建造者1
class ConcreteBuilder1 : public Builder{
private:
    Product *product = new Product();
public:
    ~ConcreteBuilder1(){
        cout << "jjjj" <<endl;
        try {
            delete product; product = nullptr;
        }
        catch(const std::exception& e) {
            std::cerr << e.what() << '\n';
        }
    }
    void BuildPartA(){
        product->Add("部件 A");
    }

    void BuildPartB(){
        product->Add("部件 B");
    }

    Product* GetResult(){
        return product;
    }
};

// 建造者2
class ConcreteBuilder2 : public Builder{
private:
    Product *product = new Product();
public:
    ~ConcreteBuilder2(){
        cout << "删除成功?? " <<endl;
        delete product; product = nullptr;
    }
    void BuildPartA(){
        product->Add("部件 X");
    }

    void BuildPartB(){
        product->Add("部件 Y");
    }

    Product* GetResult(){
        return product;
    }
};

// 指挥者 Director类
class Director{
public:
    ~Director(){
        cout << "delete Direct" <<endl;
    }
    void Construct(Builder *builder){
        builder->BuildPartA();
        builder->BuildPartB();
    }
};

int main(int argc, char const *argv[])
{
    Builder *b1 = new ConcreteBuilder1();
    Builder *b2 = new ConcreteBuilder2();

    Director *director = new Director();

    director->Construct(b1);
    Product *p1 = b1->GetResult();
    p1->Show();

    director->Construct(b2);
    Product *p2 = b2->GetResult();
    p2->Show();

    delete b1; b1 = nullptr;
    delete b2; b2 = nullptr;
    delete director; director = nullptr;
    // 下面这俩会报错, 因为已经在上面b1和b2析构了
    // delete p1; p1 = nullptr;
    // delete p2; p2 = nullptr;
    // 注意这里的Builder类的析构函数必须定义成virtual, 不然就无法删除子类实例
    
    return 0;
}

3. 应用

3.1 做汉堡咯

三层
产品
建造者
指挥者
客户

// 产品类
class Product{
private:
    list<string> parts; // 使用链表创建部件
public:
    virtual ~Product(){}
    // 添加产品部件
    void Add(string part){
        parts.push_back(part);
    }

    void Show(){
        cout<< "产品创建 ... " <<endl;
        for(auto &s : parts){
            cout << s <<endl;
        }
    }
};

// Builder类
class Builder{
public:
    virtual ~Builder(){}
    virtual void BuildPartA() = 0;
    virtual void BuildPartB() = 0;
    virtual void BuildPartC() = 0;
    virtual Product *GetResult() = 0;
};

// 具体建造者类
// 烧鸡建造
class ConcreteBuilderSJ : public Builder{
private:
    Product *product = new Product();
public:
    ~ConcreteBuilder1(){
        delete product; product = nullptr;
    }
    void BuildPartA(){
        product->Add("油炸10小时");
    }

    void BuildPartB(){
        product->Add("咸盐20斤");
    }

    void BuildPartC(){
        product->Add("芥末1kg");
    }
    Product* GetResult(){
        return product;
    }
};

// 建造者 芥末鸡
class ConcreteBuilderJMJ : public Builder{
private:
    Product *product = new Product();
public:
    ~ConcreteBuilder2(){
        cout << "删除成功?? " <<endl;
        delete product; product = nullptr;
    }
    void BuildPartA(){
        product->Add("油炸1小时");
    }

    void BuildPartB(){
        product->Add("咸盐2斤");
    }

    void BuildPartC(){
        product->Add("芥末100吨");
    }
    Product* GetResult(){
        return product;
    }
};

// 指挥者 Director类
class Director{
public:
    ~Director(){
        cout << "delete Direct" <<endl;
    }
    void Construct(Builder *builder){
        builder->BuildPartA();
        builder->BuildPartB();
        builder->BuildPartC();
    }
};

int main(int argc, char const *argv[])
{
    Builder *b1 = new ConcreteBuilderSJ(); // 烧鸡厨师
    Builder *b2 = new ConcreteBuilderJMJ(); // 芥末鸡厨师

    Director *director = new Director(); // 后厨老大

    director->Construct(b1);  // 老大要求烧鸡厨师创建个烧鸡 
    Product *p1 = b1->GetResult();// 烧鸡厨师产出一个烧鸡
    p1->Show(); // 烧鸡给顾客

    director->Construct(b2);
    Product *p2 = b2->GetResult();
    p2->Show();

    delete b1; b1 = nullptr;
    delete b2; b2 = nullptr;
    delete director; director = nullptr;
    return 0;
}

标签:Product,p1,void,product,C++,肯德基,设计模式,public,delete
来源: https://blog.csdn.net/qq_32460819/article/details/120610566