文章目录

  • 1. 理论基础
  • 2. 逻辑代码
  • 3. 应用
    • 3.1 做汉堡咯

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

本文还涉及到两个知识点

  • delete
    在本文之前,我的delete都是使用的delete p1, p2, p3这样的格式, 但是这样做是错误的, 因为上面的语句表达的是: delete p1; p2; p3, 因此只删除了p1; 此外在C++中, 由于编译器不负责delete p1这样的指针, 因此当delete执行完毕后, 只回收了p1指向的堆内存空间, 但是p1这个指针依然真实存在的, 此时p1已经成为了野指针, 因此delete p1后, 还需要把p1删除, 删除的格式是 p1 = nullptr, 这样后面就无法在访问这个p1的指针了
  • 析构函数
    当子类继承基类, 子类中会生成指针对象, 并且要在子类析构时回收这个对象, 那么必须要在基类的析构函数定义为虚函数, 这样一旦有多态的情况就可以对子类里面的指针对象进行回收了.
class A{public: virtual ~A(){} // 命令1virtual 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. 逻辑代码


如上图所示:

  • Builder相当于制作汉堡的抽象类, 为Product对象的各个部件指定的抽象接口
  • ConcreteBuilder相当于具体实现制作汉堡的各个细节流程
  • Director指挥者, 根据用户需要构建不同的汉堡
  • 什么时候需要使用到建造者模式呢? 用于创建一些复杂对象, 这些对象内部构建间的构造顺序通常是稳定的, 但对象内部的构建通常面临着复杂的变化
#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;
}

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

  1. 建造者模式详解:建造随意搭配的肯德基套餐

    快捷导航 一.概要 二.实现案例 构建一份肯德基套餐 代码实现 产品类 建造者类 测试类 指挥者(可选) 三.总结 一.概要 建造者模式(Builder Pattern)是五种创建型设计模式之一,它将 ...

  2. java设计模式建造_java设计模式-建造者模式

    建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创造不同的表示. 建造者模式将一个产品的内部表象和产品的生成过程分割开来,建造对象的时候只需要指定需要建造的类型,而不必了解具体的 ...

  3. Python设计模式-建造者模式

    Python设计模式-建造者模式 代码基于3.5.2,代码如下; #coding:utf-8 #建造者模式 class Burger():name = ""price = 0.0d ...

  4. 说说设计模式~建造者模式(Builder)

    建造者模式是我的"设计模式"里创建型模式里的最后一篇,这种模式在实现中,很多架构都用到了,如MVC,MVP,MVVM,它们都是有建造者模式的精髓的,即,创建与表现分享,我们的MVC ...

  5. 设计模式 建造者模式_设计模式:建造者

    设计模式 建造者模式 有时需要在应用程序中创建一个复杂的对象. 一种解决方案是Factory模式,另一种是Builder设计模式. 在某些情况下,您甚至可以结合使用这两种模式. 但是在本文中,我想研究 ...

  6. Python 设计模式 - 建造者模式

    精通Python设计模式第二版 第 2 章 建造者模式 学习笔记 建造者模式 假设我们要创建一个由对各部分组成的独享,而且创建过程需要一步一步地完成.只有创建了所有的部分,该对象才是完成的.这种需求可 ...

  7. 设计模式-建造者模式C++

    一.定义 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式的基本思想是使用简单对象一步步构建一个复杂的对象.属于创建型模式. 建造者模式更关注各对象的组装过程,实现 ...

  8. [设计模式] - 建造者模式

    文章目录 一.建造者模式的简介 1. 什么是建造者模式 2. 建造者模式使用的业务场景 二.传统方式实现 1. 利用有参构造 三.建造者模式实现 第一步: 创建产品对象 第二步: 创建Builder接 ...

  9. c#设计模式-建造者模式

    意图 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 场景 在电脑城装机总有这样的经历.我们到了店里,先会有一个销售人员来询问你希望装的机器是怎么样的配置,他会给你一些建议,最 ...

最新文章

  1. 90后售楼人员的肺腑之言:再便宜你也不能买的房子(转)
  2. 交换技术、覆盖技术、虚拟存储技术的区分
  3. Codeforces 1344 题解
  4. php三个数字比较大小排序,php中常用的4种实现数字大小排序的冒泡选择等算法函数代码...
  5. 三十三、深入Python中的itertools模块
  6. python爬虫常见的那点问题!
  7. 20210322 :贪心思想力扣典型题目合集
  8. fianl属性 java_Java反射如何有效的修改final属性值详解
  9. 怎样做网站,需要考虑的几个seo因素
  10. 跑腿 php,啦啦外卖跑腿小程序配置详情
  11. 叉乘:基于虚拟线圈法的车流量统计
  12. c语言控制科学计数法指数位数,控制科学计数法的指数位数
  13. w ndows 10关机快捷键,win10系统
  14. office 2003安装/卸载“无法打开此修补程序包”错误的解决方案
  15. elasticsearch for windows
  16. 白鹭引擎王泽:重度H5游戏性能优化技巧
  17. Problem 1004: 蛤玮打扫教室(区间覆盖端点记录)
  18. 稳中求变,试着提高时间管理能力
  19. 人间仙境 绵山水涛沟秋季美景
  20. layui模板引擎的使用

热门文章

  1. 奥鹏计算机基础计算机病毒是指,奥鹏教育《计算机应用基础》在线考核A卷.doc...
  2. imx6ull 14*14 平台使用mfgtools下载代码出现UTP Waiting for device to appear错误
  3. 为什么计划总是坚持不下去?
  4. vue项目屏幕自适应_vue项目自适应屏幕和浏览器
  5. mac 访问局域网其他电脑上的虚拟机
  6. 课堂秩序难管理?这个方法造福师生
  7. 图解PKCS#1——第四部分 签名验签方案
  8. Python编程:Python2和Python3环境下re正则匹配中文
  9. 感觉编程还是需要逐渐熟练的技术工种吧,分几个维度来描述。
  10. mac怎么打开rar文件