原文转载:https://blog.csdn.net/sinat_21107433/article/details/102635881

1.建造者模式简介

建造者模式将客户端与包含多个部件的复杂对象的创建过程分离,客户端不必知道复杂对象的内部组成方式与装配方式(就好像Jungle不知道到底是如何把大象装进冰箱一样),只需知道所需建造者的类型即可。

建造者模式定义:

建造者模式:

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

同样的构建过程可以创建不同的表示”??这句话是什么意思呢?想象一下,建造一栋房子,建造过程无非都是打地基、筑墙、安装门窗等过程,但不同的客户可能希望不同的风格或者过程,最终建造出来的房子当然就呈现不同的风格啦!

2.建造者模式结构

建造者模式的结构包含以下几个角色:

  • 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
  • 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果。
  • 产品(Product):具体的产品对象
  • 指挥者(Director): 构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。

建造者模式UML类图如下:

04 建造者模式

3.建造者模式代码实例

考虑这样一个场景,如下图:

Jungle想要建造一栋简易的房子(地板、墙和天花板),两个工程师带着各自的方案找上门来,直接给Jungle看方案和效果图。犹豫再三,Jungle最终选定了一位工程师……交房之日,Jungle满意的看着建好的房子,开始思考:这房子究竟是怎么建成的呢?这地板、墙和天花板是怎么建造的呢?工程师笑着说:“It's none of your business”

04 建造者模式

 UML图如下:

04 建造者模式

3.1.定义产品类House

 
  1. //产品类House

  2. class House

  3. {

  4. public:

  5. House(){}

  6. void setFloor(string iFloor){

  7. this->floor = iFloor;

  8. }

  9. void setWall(string iWall){

  10. this->wall = iWall;

  11. }

  12. void setRoof(string iRoof){

  13. this->roof = iRoof;

  14. }

  15. //打印House信息

  16. void printfHouseInfo(){

  17. printf("Floor:%s\t\n", this->floor.c_str());

  18. printf("Wall:%s\t\n", this->wall.c_str());

  19. printf("Roof:%s\t\n", this->roof.c_str());

  20. }

  21. private:

  22. string floor;

  23. string wall;

  24. string roof;

  25. };

 House是本实例中的产品,具有floor、wall和roof三个属性。

3.2.定义建造者

3.2.1.定义抽象建造者AbstractBuilder

 
  1. //抽象建造者AbstractBall

  2. class AbstractBuilder

  3. {

  4. public:

  5. AbstractBuilder(){

  6. house = new House();

  7. }

  8. //抽象方法:

  9. virtual void buildFloor() = 0;

  10. virtual void buildWall() = 0;

  11. virtual void buildRoof() = 0;

  12. virtual House *getHouse() = 0;

  13.  
  14. House *house;

  15. };

3.2.2.定义具体建造者 

 
  1. //具体建造者ConcreteBuilderA

  2. class ConcreteBuilderA :public AbstractBuilder

  3. {

  4. public:

  5. ConcreteBuilderA(){

  6. printf("ConcreteBuilderA\n");

  7. }

  8. //具体实现方法

  9. void buildFloor(){

  10. this->house->setFloor("Floor_A");

  11. }

  12. void buildWall(){

  13. this->house->setWall("Wall_A");

  14. }

  15. void buildRoof(){

  16. this->house->setRoof("Roof_A");

  17. }

  18. House *getHouse(){

  19. return this->house;

  20. }

  21. };

  22.  
  23. //具体建造者ConcreteBuilderB

  24. class ConcreteBuilderB :public AbstractBuilder

  25. {

  26. public:

  27. ConcreteBuilderB(){

  28. printf("ConcreteBuilderB\n");

  29. }

  30. //具体实现方法

  31. void buildFloor(){

  32. this->house->setFloor("Floor_B");

  33. }

  34. void buildWall(){

  35. this->house->setWall("Wall_B");

  36. }

  37. void buildRoof(){

  38. this->house->setRoof("Roof_B");

  39. }

  40. House *getHouse(){

  41. return this->house;

  42. }

  43. };

3.3.定义指挥者

 
  1. //指挥者Director

  2. class Director

  3. {

  4. public:

  5. Director(){}

  6. //具体实现方法

  7. void setBuilder(AbstractBuilder *iBuilder){

  8. this->builder = iBuilder;

  9. }

  10. //封装组装流程,返回建造结果

  11. House *construct(){

  12. builder->buildFloor();

  13. builder->buildWall();

  14. builder->buildRoof();

  15. return builder->getHouse();

  16. }

  17. private:

  18. AbstractBuilder *builder;

  19. };

3.4.客户端代码示例

 
  1. #include "BuilderPattern.h"

  2.  
  3. int main()

  4. {

  5. //抽象建造者

  6. AbstractBuilder *builder;

  7. //指挥者

  8. Director *director = new Director();

  9. //产品:House

  10. House *house;

  11.  
  12. //指定具体建造者A

  13. builder = new ConcreteBuilderA();

  14. director->setBuilder(builder);

  15. house = director->construct();

  16. house->printfHouseInfo();

  17.  
  18. //指定具体建造者B

  19. builder = new ConcreteBuilderB();

  20. director->setBuilder(builder);

  21. house = director->construct();

  22. house->printfHouseInfo();

  23.  
  24. system("pause");

  25. return 0;

  26. }

 3.5.效果

04 建造者模式

4.建造者模式总结

 从客户端代码可以看到,客户端只需指定具体建造者,并作为参数传递给指挥者,通过指挥者即可得到结果。客户端无需关心House的建造方法和具体流程。如果要更换建造风格,只需更换具体建造者即可,不同建造者之间并无任何关联,方便替换。从代码优化角度来看,其实可以不需要指挥者Director的角色,而直接把construct方法放入具体建造者当中。

优点:

  • 建造者模式中,客户端不需要知道产品内部组成细节,将产品本身和产品的创建过程分离,使同样的创建过程可以创建不同的产品对象;
  • 不同建造者相互独立,并无任何挂链,方便替换。

缺点:

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  •  如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大

适用环境:

  • 需要生成的产品对象有复杂的内部结构(通常包含多个成员变量);
  • 产品对象内部属性有一定的生成顺序;
  • 同一个创建流程适用于多种不同的产品。

相关文章:

猜你喜欢
  • 2021-08-19
  • 2021-08-29
  • 2021-12-02
  • 2021-12-02
相关资源
相似解决方案