本文还涉及到两个知识点
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(){} // 命令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、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。
2、JAVA 中的 StringBuilder。
优点:
1、建造者独立,易扩展。 2、便于控制细节风险。
缺点:
1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景:
1、需要生成的对象具有复杂的内部结构。 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; }
三层
产品
建造者
指挥者
客户
// 产品类 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; }