一、建造者模式
1. 什么是建造者模式
Bulider Pattern,建造者模式,也叫做生成器模式,是一种对象创建型模式。建造者模式用于创建具有多个部件的复合对象,并隐藏了复合对象的创建过程,不同的部件建造者(Builder生成器)有不同的建造方法。通过建造者模式实现了对象的构建和对象的表示的分离,也就是说,通过同样的构建过程(建造逻辑)可以创建出不同的表示(使用不同的建造者产生不同的建造方式)。
建造者模式中的4种角色:
- 抽象建造者角色Builder:为建造各个组件提供统一的抽象接口;
- 具体建造者角色ConcreteBuilder:实现抽象建造者提供的抽象接口,定义各个组件的建造方法,是组件建造的具体实施者;
- 指挥者Director:调用具体建造者来建造产品的各个组件,指挥者并不知道产品的具体信息,指挥者只负责规定并保证各个组件的建造过程和建造逻辑(指挥建造的过程,比如先装发动机再装轮子);
- 产品角色Product:被建造的复杂对象,包含组合对象的各个部件;
2. 建造者模式的实现
首先我们定义一个汽车产品类,这个汽车包含外壳、发动机、车轮三个部件,并且汽车产品类中应该包含设置各个部件和获取各个部件的方法。汽车产品类是我们最终要建造的目标,是客户的需求。
1. //最终产品类:汽车 2. class CarProduct 3. { 4. public: 5. void set_shell(string shell) //建造汽车外壳 6. { 7. this->shell = shell; 8. } 9. void set_engine(string engine) //建造汽车发动机 10. { 11. this->engine = engine; 12. } 13. void set_whell(string whell) //建造汽车轮子 14. { 15. this->whell = whell; 16. } 17. //获取属性 18. string get_shell() 19. { 20. return this->shell; 21. } 22. string get_engine() 23. { 24. return this->engine; 25. } 26. string get_whell() 27. { 28. return this->whell; 29. } 30. private: 31. string shell; //外壳 32. string engine; //发动机 33. string whell; //轮子 34. };
定义一个抽象的建造者基类,类中统一了建造部件的接口和返回产品成品的方法。
1. //建造者基类:抽象施工单位 2. class Builder 3. { 4. public: 5. virtual void builder_shell() = 0; //汽车外壳的建造方式接口 6. virtual void builder_engine() = 0; //发动机的建造方式 7. virtual void builder_whell() = 0; //车轮的建造方式 8. virtual CarProduct* get_car() = 0; //返回建造好的汽车产品 9. };
定义具体建造者类,具体建造者类是产品部件的具体建造者,也就是汽车的生产商,我们定义两个汽车生产商,一个厂家生产卡车,一个厂家生产火车。
1. //具体的建造者:具体施工单位、具体的建造方式 2. class TruckBuilder : public Builder //卡车建造商 3. { 4. private: 5. CarProduct* m_car; 6. public: 7. TruckBuilder() 8. { 9. this->m_car = new CarProduct; 10. } 11. virtual void builder_shell() 12. { 13. this->m_car->set_shell("卡车外壳"); 14. } 15. virtual void builder_engine() 16. { 17. this->m_car->set_engine("卡车发动机"); 18. } 19. virtual void builder_whell() 20. { 21. this->m_car->set_whell("卡车轮子"); 22. } 23. virtual CarProduct* get_car() 24. { 25. return this->m_car; 26. } 27. }; 28. class TrainBuilder : public Builder //火车建造商 29. { 30. private: 31. CarProduct* m_car; 32. public: 33. TrainBuilder() 34. { 35. this->m_car = new CarProduct; 36. } 37. virtual void builder_shell() 38. { 39. this->m_car->set_shell("火车外壳"); 40. } 41. virtual void builder_engine() 42. { 43. this->m_car->set_engine("火车发动机"); 44. } 45. virtual void builder_whell() 46. { 47. this->m_car->set_whell("火车轮子"); 48. } 49. virtual CarProduct* get_car() 50. { 51. return this->m_car; 52. } 53. };
最后,应该定义一个指挥者,指挥者是汽车的设计师,它负责规划建造汽车的逻辑步骤,指挥汽车厂家(具体建造者)干活,而具体的工作有汽车厂家去干,所以指挥者不关心汽车的具体细节,只负责设计建造汽车各个部件的逻辑关系,比如先制造汽车外壳,然后安装发动机,最后安装车轮。
1. //指挥者:设计师,负责设计建造逻辑 2. class Director 3. { 4. public: 5. Director(Builder* builder) 6. { 7. this->m_builder = builder; 8. } 9. //建造逻辑 10. void builder_logic() 11. { 12. //1.先建造车的外壳 13. this->m_builder->builder_shell(); 14. cout << "先建造车的外壳\t"; 15. //2.再安装发动机 16. this->m_builder->builder_engine(); 17. cout << "再安装发动机\t"; 18. //3.最后安装车轮 19. this->m_builder->builder_whell(); 20. cout << "最后安装车轮\n"; 21. } 22. private: 23. Builder* m_builder; 24. };
最后是根据客户需求去建造汽车,假设客户需要一辆卡车。
1. int main() 2. { 3. CarProduct* myCar = NULL; 4. Builder* tempBuilder = NULL; 5. Director* carDector = NULL; 6. 7. //需求:建造一辆卡车 8. //首先找一个卡车建造商 9. tempBuilder = new TruckBuilder; 10. //把建造商交给指挥者(设计师)管理 11. carDector = new Director(tempBuilder); 12. //开始建造 13. carDector->builder_logic(); 14. //获取产品 对象的建造逻辑和产品的表示分离 15. myCar = tempBuilder->get_car(); 16. cout << "======产品信息======" << endl; 17. cout << myCar->get_shell() << endl; 18. cout << myCar->get_engine() << endl; 19. cout << myCar->get_whell() << endl; 20. cout << "====================" << endl; 21. delete myCar; 22. delete carDector; 23. delete tempBuilder; 24. }
假如客户提出新需求,需要一辆火车,那么我们直接让指挥者去指挥火车厂商生产即可。
1. //新需求:需要一辆火车 2. tempBuilder = new TrainBuilder; 3. carDector = new Director(tempBuilder); 4. carDector->builder_logic(); 5. myCar = tempBuilder->get_car(); 6. cout << "======产品信息======" << endl; 7. cout << myCar->get_shell() << endl; 8. cout << myCar->get_engine() << endl; 9. cout << myCar->get_whell() << endl; 10. cout << "====================" << endl; 11. delete myCar; 12. delete carDector; 13. delete tempBuilder;
3. 建造者模式和工厂模式对比
建造者模式和工厂模式的区别是:工厂模式强调的是结果,不考虑对象的建造过程,只关注产生一个客户所需要的结果。比如,客户需要一辆大众汽车,那么就直接使用大众汽车工厂来生产一辆大众汽车,只关注大众汽车这个结果,不关心汽车外壳、发动机、轮子等部件的建造过程。建造者模式强调的是建造过程,要关注每一个部件的建造方式,以及各个部件的建造逻辑,最终组合出需要的对象。
二、原型模式
1. 什么是原型模式
Prototype Pattern,原型模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例,所以称之为Clone,被复制出来的对象具有和原型一摸一样的数据,并且在通过Clone创造另一个一模一样的对象时,不需要知道创造的过程。根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
2. 原型模式的实现
既然原型模式是复制一个一模一样的对象,那么就一定要注意潜在的深拷贝浅拷贝问题。
1. #include <iostream> 2. using namespace std; 3. 4. #include <String> 5. 6. class MyString 7. { 8. public: 9. virtual MyString* Clone() = 0; 10. virtual void print_str() = 0; 11. }; 12. 13. class Hello : public MyString 14. { 15. private: 16. int len; 17. string str; 18. public: 19. Hello() 20. { 21. this->len = 5; 22. this->str = "Hello"; 23. } 24. virtual MyString* Clone() 25. { 26. Hello* temp = new Hello; 27. *temp = *this; 28. return temp; 29. } 30. virtual void print_str() 31. { 32. cout << "len:" << len << " str:" << str << endl; 33. } 34. }; 35. 36. int main() 37. { 38. MyString* h1 = new Hello; 39. h1->print_str(); 40. MyString* h2 = h1->Clone(); 41. h2->print_str(); 42. 43. delete h1; 44. delete h2; 45. 46. system("pause"); 47. return 0; 48. }
三、创建型设计模式总结
顾名思义,创建型设计模式就是处理对象创建过程的设计模式。创建型模式主要是将系统所需要的用到的具体类封装起来,在内部实现这些具体类的创建和结合,并对外隐藏这个过程细节。创建型设计模式主要包括:
- 单例模式
- 简单工厂模式
- 工厂模式
- 抽象工厂模式
- 建造者模式
- 原型模式
其中,简单工厂模式因为不符合开闭原则,它不属于标准的23种设计模式。