C++ 建造者模式(Builder)

最近在学设计模式,对于建造者模式找了大量的资料,最后看到这篇文章写得比较通俗易懂(建造者模式及C++实现),本文在这篇文章的基础上进行学习。

1 核心

建造者模式适合于产品各个模块内建造过程多变,而各个模块相对的建造顺序稳定的情况。

建造者模式的类图如下:

建造者模式

2 具体实现

2.1 产品product

产品拥有三个参数para,有三个方法分别进行设置set,还有一个展示参数的方法show。
Product.h

#pragma once
class Product
{
public:
	Product();
	~Product();
	//产品拥有分别设置三个参数的三个方法
	void setA(int a);
	void setB(int b);
	void setC(int c);
	//展现产品的方法
	void show();
private:
	//产品拥有三个参数
	int paraA;
	int paraB;
	int paraC;
};

Product.cpp

#include "Product.h"
#include<iostream>
using std::cout;
using std::endl;
Product::Product(){}
Product::~Product(){}

void Product::setA(int a)
{
	paraA = a;
}

void Product::setB(int b)
{
	paraB = b;
}

void Product::setC(int c)
{
	paraC = c;
}

void Product::show()
{
	cout << paraA << " " << paraB << " " << paraC << endl;
}

2.2 建造者Builder

建造者基类提供建造产品各个模块的接口,建造者具体子类实现基类接口,建造具体的产品。产品各个模块内建造过程的需求变化,可增加建造者具体子类,以满足模块内建造过程变化的需求。
AbstractBuilder.h

#pragma once
#include"Product.h"
class AbstractBuilder
{
public:
	AbstractBuilder();
	virtual ~AbstractBuilder();
	//产品Product内拥有三个模块,对应提供给具体子类三个建造接口
	//设置为纯虚函数,子类必须实现
	virtual void buildA(int) = 0;
	virtual void buildB(int) = 0;
	virtual void buildC(int) = 0;
	//给外界提供获取产品的接口
	virtual Product* getProduct() = 0;
	//创建产品毛坯,需要通过三个模块的建造才能出厂。
	virtual void createProduct() = 0;
};

AbstractBuilder.cpp

#include "AbstractBuilder.h"
AbstractBuilder::AbstractBuilder(){}
AbstractBuilder::~AbstractBuilder(){}

ConcreteBuilder.h

#pragma once
#include "AbstractBuilder.h"
class ConcreteBuilder :
	public AbstractBuilder
{
public:
	ConcreteBuilder();
	~ConcreteBuilder();
	//实现基类提供的接口
	void buildA(int);
	void buildB(int);
	void buildC(int);
	Product* getProduct();
	void createProduct();
private:
	//建造对象
	Product* curProduct;
};

ConcreteBuilder.cpp

#include "ConcreteBuilder.h"
ConcreteBuilder::ConcreteBuilder(){}
ConcreteBuilder::~ConcreteBuilder(){}

void ConcreteBuilder::createProduct()
{
	curProduct = new Product();
}
void ConcreteBuilder::buildA(int a)
{
	curProduct->setA(a);
}
void ConcreteBuilder::buildB(int b)
{
	curProduct->setB(b);
}
void ConcreteBuilder::buildC(int c)
{
	curProduct->setC(c);
}
Product* ConcreteBuilder::getProduct()
{
	return curProduct;
}

2.3 导演Director

虽然Builder提供了对Product各个模块的建造方法,但是各个模块的建造顺序却没有定下来,而这个建造顺序是相对稳定的,也就是不需要修改的,因此独立出一个Director类来确定建造顺序,同时将这个稳定的建造顺序方法提供给客户即可。
对于客户来说,我想要使用某一种建造方法ConcreteBuilder做出我的产品Product,导演Director你给我造出来,我只需要从你这里得到产品Product即可。
Director.h

#pragma once
#include"AbstractBuilder.h"
class Director
{
public:
	//客户需要告知导演使用哪一种建造方法
	Director(AbstractBuilder* builder);
	~Director();
	//客户需要告知建造过程/产品的核心参数
	void construct(int a, int b, int c);
	//提供客户产品,客户也可以直接使用Builder获取该产品(这是我自己加上的方法)
	Product* getProduct();

private:
	//导演需要知道自己在导演哪一种建造过程
	AbstractBuilder *curBuilder;
};

2.4 客户端使用Main

可以开始使用建造者模式建造我们的产品了。

#pragma once
#include"Director.h"
#include"ConcreteBuilder.h"//必须包含,否则无从找到具体建造者类
#include<iostream>
using std::cout;
using std::endl;

int main()
{
	//需要告知Director使用哪一种具体的建造方法
	AbstractBuilder* builder = new ConcreteBuilder();
	Director* director = new Director(builder);
	//需要告知Director建造的参数
	director->construct(5, 2, 33);
	//可以从Director获取产品
	Product*product1 = director->getProduct();
	product1->show();
	//也可以直接从建造者手上获取产品
	Product*product2 = builder->getProduct();
	product2->show();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

2.5 需求改变

客户说:现在需求变了,你这个系统需要对我给的参数做进一步处理才能加到产品上,我要它们的平方作为产品参数,而不是直接设置成产品参数。
开发者说:好,马上给你修改。
开发者想:我只需要添加一个具体的建造子类即可满足你的需求。
ConcreteBuilder1.h

#pragma once
#include "AbstractBuilder.h"
class ConcreteBuilder1 :
	public AbstractBuilder
{
public:
	ConcreteBuilder1();
	~ConcreteBuilder1();
	void buildA(int);
	void buildB(int);
	void buildC(int);
	Product* getProduct();
	void createProduct();
private:
	Product* curProduct;
};

ConcreteBuilder1.cpp

#include "ConcreteBuilder1.h"
ConcreteBuilder1::ConcreteBuilder1(){}
ConcreteBuilder1::~ConcreteBuilder1(){}

void ConcreteBuilder1::buildA(int a)
{
	curProduct->setA(a*a);
}
void ConcreteBuilder1::buildB(int b)
{
	curProduct->setB(b*b);
}
void ConcreteBuilder1::buildC(int c)
{
	curProduct->setC(c*c);
}

Product* ConcreteBuilder1::getProduct()
{
	return curProduct;
}
void ConcreteBuilder1::createProduct()
{
	curProduct = new Product();
}

客户端Main.h

#pragma once
#include"Director.h"
#include"ConcreteBuilder1.h"
#include<iostream>
using std::cout;
using std::endl;

int main()
{
	AbstractBuilder* builder = new ConcreteBuilder1();
	Director* director = new Director(builder);
	director->construct(5, 2, 33);
	Product*product1 = director->getProduct();
	product1->show();
	Product*product2 = builder->getProduct();
	product2->show();
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述
客户想:这个开发者不错啊,对我需求的响应真快。
开发者想:小case啦,因为我使用了建造者模式。

3 讨论

如果不使用建造者模式,对上述需求需求改动Product类的set方法,违反了OO设计原则:对修改封闭,对扩展开放原则。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值