服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 详解C++设计模式编程中建造者模式的实现

详解C++设计模式编程中建造者模式的实现

2021-03-26 14:21曾经的你 C/C++

这篇文章主要介绍了C++设计模式编程中建造者模式的实现,建造者模式将一个复杂对象的构建于它的表现分离,可以减少代码冗余,需要的朋友可以参考下

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这是建造者模式的标准表达,不过看着让人迷惑,什么叫构建和表示的分离?一个对象使用构造函数构造之后不就固定了,只有通过它方法来改变它的属性吗?而且还要同样的构建过程搞出不同的表示,怎么可能呢?多写几个构造函数?

其实多写几个构造函数,根据不同参数设置对象不同的属性,也可以达到这样的效果,只是这样就非常麻烦了,每次要增加一种表示就要添加一个构造函数,将来构造函数会多得连自己都不记得了,这违背了开放-封闭的原则。

要不就只能设计几个set函数,每次属性不一样了,我就构造一个对象,然后用set函数改变对象的属性。这样也可以达到效果。只是代码就会非常冗余了,每个要用到这个对象的地方,都要写上好几句语句,一旦对象有点什么变化,还得到处都改一遍,这样就很容易出错,以后别人看着这种神逻辑和神代码估计也会崩溃了。而且这也违背了依赖倒转的原则。

于是大神们就开始想了,不能加很多构造函数,也不能直接用一堆set函数,然后发现,有些对象的构建是固定的几个步骤的,就像一条流水线一样,任何的产品都是通过每一个固定的步骤拼凑出来的。例如说一部手机,先放主板,再放屏幕,再放电池,再放外壳,贴个膜就能卖几千了,每次推出新产品,就换个更好的主板,换个大点的屏幕,再整个大容量电池,贴个超牛B的高透膜,又能卖出个新价钱。就是说,这些步骤都没有变,变的只是每个部分的东西。

这就是大神的厉害之处了,透过现象看本质,基本有变的,有不变的,那敢情好,面向对象的一个重要指导思想就是,封装隔离变化的,留出不变的。于是他们就用一个Builder类把步骤中的每个部分封装起来,这个类的主要作用就是生产每个部件,再抽象一下提升高度,这样就依赖倒转了,这样每次只需要添加一个类,这个类还是这几个部分,只是内部的实现已经不一样了,这样就满足了开放-封闭的原则了。但还是有一个问题,光有Builder类还不行,虽然产品的每个部分都有对应的函数,但是用起来的话,还是跟前面说的set函数一样,一用就要使用一大堆函数,也就是这变的东西是封装起来了,但这不变的东西还没留出来。这时,就添加一个Director类,这个类就是专门规定组装产品的步骤的,这样只要告诉Director使用哪个Builder,就能生产出不同的产品,对于客户端来说,只看到用了Director的一个construct函数,甚是方便。

再反过来看建造者模式的定义,构建指的就是生产一个产品的步骤,表示就是每个产品部分的具体实现,通过Director封装步骤,通过Builder封装产品部分的实现,再把他两隔离开,就能隔离变的,留出不变的供客户端使用。

详解C++设计模式编程中建造者模式的实现

图中可以看到,Product是必须要知道,没有抽象,但是这个产品却可以由不同的部分组合而成。Director里的construct也是固定,没有抽象出来,如果要更改步骤,也要添加一个函数,或者再添一个Diector,所以建造者模式一般应用于步骤不会发生大的变化,而产品会发生大变化的情况。

常用的场景
C#中的StringBuilder就是一个建造者的例子,但只是一个建造者,还缺一个Director,不能算一个完整的建造者模式。建造者模式一般应用于构建产品的步骤(也可以称为算法)不变,而每个步骤的具体实现又剧烈变化的情况。

优点
1.隔离了构建的步骤和具体的实现,为产品的具体实现提供了灵活度。

2.封装和抽象了每个步骤的实现,实现了依赖倒转原则。

3.封装了具体的步骤,减少了代码的冗余。

缺点
1.要求构建产品的步骤(算法)是不能剧烈变化的,最好是不变的,这样就影响了灵活度。

实例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
  
//抽象类,用来安排创建人的具体流程,其他类必须遵循这个流程,但是可以自己具体实现
class CPersonBuilder
{
public:
 virtual void BuildHead()=0;
 virtual void BuildBody()=0;
 virtual void BuildArmLeft()=0;
 virtual void BuildArmRight()=0;
 virtual void BuildLegLeft()=0;
 virtual void BuildLegRight()=0;
};
  
//创建瘦子的类
class CThinPersonBuilder:public CPersonBuilder
{
public:
 CThinPersonBuilder()
 {
 cout<<"is creating thin person "<<endl<<endl;
 }
 ~CThinPersonBuilder()
 {
 cout<<"is finished for thin person"<<endl<<endl;
 }
public:
 void BuildHead()
 {
 cout<<"BuildHead"<<endl;
 }
 void BuildBody()
 {
 cout<<"BuildBody(thin)"<<endl;
 }
 void BuildArmLeft()
 {
 cout<<"BuildArmLeft"<<endl;
 }
 void BuildArmRight()
 {
 cout<<"BuildArmRight"<<endl;
 }
 void BuildLegLeft()
 {
 cout<<"BuildLegLeft"<<endl;
 }
 void BuildLegRight()
 {
 cout<<"BuildLegRight"<<endl;
 }
};
 //创建胖子的类
class CFatPersonBuilder:public CPersonBuilder
{
public:
 CFatPersonBuilder()
 {
 cout<<"is creating fat person"<<endl;
 }
 ~CFatPersonBuilder()
 {
 cout<<"is finished for fat person"<<endl;
 }
public:
 void BuildHead()
 {
 cout<<"BuildHead"<<endl;
 }
 void BuildBody()
 {
 cout<<"BuildBody(Fat)"<<endl;
 }
 void BuildArmLeft()
 {
 cout<<"BuildArmLeft"<<endl;
 }
 void BuildArmRight()
 {
 cout<<"BuildArmRight"<<endl;
 }
 void BuildLegLeft()
 {
 cout<<"BuildLegLeft"<<endl;
 }
 void BuildLegRight()
 {
 cout<<"BuildLegRight"<<endl;
 }
};
  
//指挥者类,用来指挥创建的人是瘦子还是胖子
class CPersonDirector
{
public:
 CPersonDirector(CPersonBuilder *p)
 {
 this->m_p=p;
 }
 const void CreatePerson(void) const
 {
 m_p->BuildHead();
 m_p->BuildBody();
 m_p->BuildArmLeft();
 m_p->BuildArmRight();
 m_p->BuildLegLeft();
 m_p->BuildLegRight();
 }
private:
 CPersonBuilder *m_p;
};
  
  
  
 
int _tmain(int argc, _TCHAR* argv[])
{
 cout<<"---------建造者模式测试案例------------------------"<<endl<<endl;
  
 CThinPersonBuilder *p_tp=new CThinPersonBuilder();
 CPersonDirector *p_dtp=new CPersonDirector(p_tp);
 p_dtp->CreatePerson();
 delete p_tp;
 delete p_dtp;
 p_tp=NULL;
 p_dtp=NULL;
 cout<<endl<<endl;
 
 CFatPersonBuilder *p_fp=new CFatPersonBuilder();
 CPersonDirector *p_dfp=new CPersonDirector(p_fp);
 p_dfp->CreatePerson();
 delete p_fp;
 delete p_dfp;
 p_fp=NULL;
 p_dfp=NULL;
 system("pause");
 return 0;
}

详解C++设计模式编程中建造者模式的实现

延伸 · 阅读

精彩推荐
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12