建造者模式
随着盒装冰淇淋越来越好卖,啃得鸡的信心越来越高。老板要得做一个大号的盒装冰淇淋 --> 冰淇淋蛋糕。
领导一句话,生产部门跑断腿。
分析发现:
冰淇淋蛋糕的组成有
必选项:蛋糕坯层、冰淇淋层
可选项:水果装饰、巧克力碎装饰、冰淇淋裱花装饰
产品部准备生产的产品有:【草莓 冰淇淋裱花蛋糕】、【抹茶 巧克力碎蛋糕】
原本的冰淇淋生产线完全不能适应,需要新的生产线。
老板觉得啃得鸡商标的溢价肯定能赚的盆满钵满;于是不经同意,还不计投入。
# 场景分析
这里不同于之前的冰棍模式在于,这里的产品的工艺是繁琐的。
这里代码重点要维护的复杂度,是产品的生产过程;而产品的结果都是冰淇淋蛋糕这个单一概念。
# 标准实现
# 需要生产的产品
class IceCreamCake
{
public:
IceCreamCake(string cakeBillet, string IceCream)
: m_cakeBillet(cakeBillet), m_IceCream(IceCream)
, m_fruit(""), m_chocolate(""), m_decoration("")
{
}
~IceCreamCake() {}
void taste()
{
if (m_fruit != "")
cout << m_fruit << "的 ";
if (m_chocolate != "")
cout << m_chocolate << "的 ";
if (m_decoration != "")
cout << m_decoration << "的 ";
cout << m_cakeBillet << "的 " << m_IceCream << "的 " << "蛋糕";
}
void setFruit(string fruit)
{
m_fruit = fruit;
}
void setChocolate(string chocolate)
{
m_chocolate = chocolate;
}
void setDecoration(string decoration)
{
m_decoration = decoration;
}
private:
string m_cakeBillet;// 必选项: 蛋糕坯层
string m_IceCream; // 必选项: 冰淇淋层
string m_fruit; // 可选项:水果装饰
string m_chocolate; // 可选项:巧克力碎装饰
string m_decoration;// 可选项:冰淇淋裱花装饰
};
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
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
# 接口类
class Builder
{
public:
Builder(string cakeBillet, string IceCream)
: m_pIceCreamCake(new IceCreamCake(cakeBillet, IceCream))
{
}
virtual ~Builder()
{
delete m_pIceCreamCake;
m_pIceCreamCake = nullptr;
}
IceCreamCake* getProduct()
{
return m_pIceCreamCake;
}
virtual void setFruit() {}
virtual void setChocolate() {}
virtual void setDecoration() {}
protected:
IceCreamCake* m_pIceCreamCake;
};
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
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
# 实现类
class ChocolateCakeBuilder : public Builder
{
public:
ChocolateCakeBuilder(string cakeBillet, string IceCream)
: Builder(cakeBillet, IceCream)
{
}
virtual ~ChocolateCakeBuilder()
{
}
virtual void setChocolate()override
{
m_pIceCreamCake->setChocolate("巧克力");
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 指挥者
class Director
{
public:
Director(Builder *builder)
: m_pBuilder(builder)
{
}
void makeCake()
{
m_pBuilder->setFruit();
m_pBuilder->setChocolate();
m_pBuilder->setDecoration();
}
private:
Builder* m_pBuilder;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# main函数
int main(int argc, char *argv[])
{
ChocolateCakeBuilder oBuilder("可可蛋糕坯", "奶油冰淇淋");
Director oDirector(&oBuilder);
oDirector.makeCake();
IceCreamCake *pCake = oBuilder.getProduct();
pCake->taste();
return 0;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
运行结果:
# 代码位置
仓库位置:https://github.com/su-dd/demo.git (opens new window)
代码位置:设计模式/Builder (opens new window)
# 感悟
作用: 建造者是为了将对应的构造和对象的使用分离;
主要应对复杂的创建场景,如 参数不固定,参数见相互影响 等。
条件定义: 一般当一个类的构成超过4个参数,且部分参数可有可无时,就认为这个类的构造已经足够复杂;可以考虑使用建造者模式,来代替多个构造函数的定义。
问题: 有时,我们只有一个类的构造十分复杂;使用建造者模式就导致类膨胀的厉害。
这时我们可以考虑使用 局部类,来实现 简化的建造者模式。
# 简化建造者实现类
class IceCreamCake
{
public:
class Builder
{
public:
Builder(string cakeBillet, string IceCream)
: m_cakeBillet(cakeBillet), m_IceCream(IceCream) , m_fruit(""), m_chocolate(""), m_decoration("")
{}
~Builder() {}
Builder& setFruit(string fruit)
{
this->m_fruit = fruit;
return *this;
}
Builder& setChocolate(string chocolate)
{
this->m_chocolate = chocolate;
return *this;
}
Builder& setDecoration(string decoration)
{
this->m_decoration = decoration;
return *this;
}
IceCreamCake* builer()
{
return new IceCreamCake(this);
}
private:
string m_cakeBillet;// 必选项: 蛋糕坯层
string m_IceCream; // 必选项: 冰淇淋层
string m_fruit; // 可选项:水果装饰
string m_chocolate; // 可选项:巧克力碎装饰
string m_decoration;// 可选项:冰淇淋裱花装饰
friend class IceCreamCake;
};
public:
~IceCreamCake() {}
void taste()
{
if (m_fruit != "")
cout << m_fruit << "的 ";
if (m_chocolate != "")
cout << m_chocolate << "的 ";
if (m_decoration != "")
cout << m_decoration << "的 ";
cout << m_cakeBillet << "的 " << m_IceCream << "的 " << "蛋糕";
}
private:
IceCreamCake(Builder* builder)
: m_cakeBillet(""), m_IceCream(""), m_fruit(""), m_chocolate(""), m_decoration("")
{
this->m_cakeBillet = builder->m_cakeBillet;
this->m_IceCream = builder->m_IceCream;
this->m_fruit = builder->m_fruit;
this->m_chocolate = builder->m_chocolate;
this->m_decoration = builder->m_decoration;
}
private:
string m_cakeBillet;// 必选项: 蛋糕坯层
string m_IceCream; // 必选项: 冰淇淋层
string m_fruit; // 可选项:水果装饰
string m_chocolate; // 可选项:巧克力碎装饰
string m_decoration;// 可选项:冰淇淋裱花装饰
};
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
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
# 简化建造者main函数
int main(int argc, char *argv[])
{
IceCreamCake* pIceCreamCake = IceCreamCake::Builder("可可蛋糕坯", "奶油冰淇淋")
.setChocolate("巧克力")
.builer();
pIceCreamCake->taste();
return 0;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
运行结果:
这里我们简化了,指挥者 和 接口类; 同时使用 局部类的方式,将建筑者类至于产品类内部。这样有效的减少了类的膨胀。
编辑 (opens new window)
上次更新: 2023/04/09, 11:59:04