【设计模式学习笔记】建造者模式和原型模式案例详解(C++实现)

简介: 【设计模式学习笔记】建造者模式和原型模式案例详解(C++实现)

一、建造者模式

1. 什么是建造者模式

Bulider Pattern,建造者模式,也叫做生成器模式,是一种对象创建型模式。建造者模式用于创建具有多个部件的复合对象,并隐藏了复合对象的创建过程,不同的部件建造者(Builder生成器)有不同的建造方法。通过建造者模式实现了对象的构建和对象的表示的分离,也就是说,通过同样的构建过程(建造逻辑)可以创建出不同的表示(使用不同的建造者产生不同的建造方式)。

建造者模式中的4种角色:

  1. 抽象建造者角色Builder:为建造各个组件提供统一的抽象接口;
  2. 具体建造者角色ConcreteBuilder:实现抽象建造者提供的抽象接口,定义各个组件的建造方法,是组件建造的具体实施者;
  3. 指挥者Director:调用具体建造者来建造产品的各个组件,指挥者并不知道产品的具体信息,指挥者只负责规定并保证各个组件的建造过程和建造逻辑(指挥建造的过程,比如先装发动机再装轮子);
  4. 产品角色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种设计模式。


相关文章
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
15天前
|
设计模式 Java Kotlin
Kotlin学习笔记 - 改良设计模式 - 迭代器模式
Kotlin学习笔记 - 改良设计模式 - 迭代器模式
24 2
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
15天前
|
设计模式 JavaScript Scala
Kotlin学习笔记 - 改良设计模式 - 责任链模式
Kotlin学习笔记 - 改良设计模式 - 责任链模式
41 0
|
15天前
|
设计模式 Java Kotlin
Kotlin 学习笔记- 改良设计模式 - 装饰者模式
Kotlin 学习笔记- 改良设计模式 - 装饰者模式
24 0
|
2月前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
33 3
|
2月前
|
C++
【C++案例】一个项目掌握C++基础-通讯录管理系统
这篇文章通过一个通讯录管理系统的C++项目案例,详细介绍了如何使用C++实现添加、显示、删除、查找、修改和清空联系人等功能。
36 3
|
2月前
|
设计模式 Java
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
Java设计模式-原型模式(3)
|
2月前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
17 0
|
3月前
|
设计模式 Java
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
文章提供了一份常用设计模式的全面介绍,包括创建型模式、结构型模式和行为型模式。每种设计模式都有详细的概念讲解、案例说明、代码实例以及运行截图。作者通过这些模式的介绍,旨在帮助读者更好地理解源码、编写更优雅的代码,并进行系统重构。同时,文章还提供了GitHub上的源码地址,方便读者直接访问和学习。
常用设计模式介绍~~~ Java实现 【概念+案例+代码】