1.组成结构
想要搞清楚建造者模式,首先先要了解建造者模式种四个角色的定位
- Product:表示被构造的复杂对象,就是我们要建造的东西,比如我们要做一个手机,手机就是product。
- Builder:建造者,这里需要着重理解的是它是一个抽象类,不负责具体的实现。沿用做手机的例子,上面说了product是手机,那么没有说这是什么类型的手机,比如华为它可以是mate40,也可以是mate50,或者mate60。用一个抽象类就可以统一一个接口,所有的手机都用这个Builder去造。总而言之,主要是为了统一抽象接口。
- ConcreteBuilder:这具体的建造者,造mate40的方法肯定不能完全适配mate60或者50。这个具体的建造方法一般会存在多个,它赋值具体的型号制造。
- Director:我有时候在疑惑为什么Director的功能不能在builder里完成,为啥非要单独拎出来。后来我想清楚了一件事情,就是builder它不提供建造流程,而只提供建造零件本身,比如做电脑。builder或者ConcreteBuilder它内部只存在BuildDisplay、BuildHost、BuildKeyBoard这种基本的建造功能,但是建造的先后顺序它是不管的。这时候就需要Director来对这个流程进行指挥,先做什么后做什么。而且不同的指挥者,建造的顺序和方式可以能不一样,这就很灵活。如果想要使用新的流程,只需要把director换掉,而不影响builder本身。ConcreteBuilder也可以去增加更多具体的产品的生产方式。
2.优缺点
优点:
- 建造者独立,易扩展。将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够让我们更加精确的控制复杂产品对象的创建过程。
- 便于控制细节风险。它隔离了复杂产品对象的创建和使用,使得相同的创建过程能够创建不同的产品。
缺点:
但是也能感受到它的缺点,我们要扩展ConcreteBuilder,前提是什么?它必须具备和其它产品的共同点,甚至要有非常多的共同点。至少流程必须类似。比如这个Builder能制造计算机,对于手机那就可能做不了了。
- 产品必须有共同点,范围有限制。
- 如内部变化复杂,会有很多的建造类,导致系统庞大。
3.应用场景
- 需要生成的对象具有复杂的内部结构。
- 需要生成的对象内部属性本身相互依赖。
- 共用Builder的各个ConcreteBuilder需要具备足够的共同点。
4.示例代码
#include <string>
#include <vector>
#include <iostream>
using namespace std;
/*
建造者模式
组装电脑:显示器 主机 键盘 鼠标
*/
/*
1. 抽象产品类
*/
class AbstractProduct
{
public:
virtual ~AbstractProduct() {}
virtual void setDisplay(string display) = 0;
virtual void setHost(string host) = 0;
virtual void setKeyBoard(string KeyBoard) = 0;
virtual void setMouse(string mouse) = 0;
virtual void show() = 0;
};
/*
2. 具体产品类
*/
class Computer :public AbstractProduct
{
public:
~Computer() {}
void setDisplay(string display)
{
m_vec.emplace_back(display);
}
void setHost(string host)
{
m_vec.emplace_back(host);
}
void setKeyBoard(string KeyBoard)
{
m_vec.emplace_back(KeyBoard);
}
void setMouse(string mouse)
{
m_vec.emplace_back(mouse);
}
void show()
{
cout << "----------组装电脑---------" << endl;
for (auto& x : m_vec)
{
cout << x << endl;
}
}
private:
vector<string> m_vec;
};
/*
3. 抽象建造者
*/
class AbstractBuilder
{
public:
//创建电脑产品
AbstractBuilder()
:product(new Computer) {}
virtual ~AbstractBuilder() {}
//抽象电脑产品创建的统一抽象接口
virtual void BuildDisplay(string display) = 0;
virtual void BuildHost(string host) = 0;
virtual void BuildKeyBoard(string KeyBoard) = 0;
virtual void BuildMouse(string mouse) = 0;
AbstractProduct* getProduct()
{
return product;
}
protected:
AbstractProduct* product;
};
/*
4. 具体建造者:具体实现抽象建造者各个部件的接口
*/
class ComputerBuilder :public AbstractBuilder
{
public:
~ComputerBuilder() {}
void BuildDisplay(string display)
{
product->setDisplay(display);
}
void BuildHost(string host)
{
product->setHost(host);
}
void BuildKeyBoard(string KeyBoard)
{
product->setKeyBoard(KeyBoard);
}
void BuildMouse(string mouse)
{
product->setMouse(mouse);
}
};
/*
5. 指挥者:安排和调度复杂对象的创建过程
*/
class Director
{
public:
Director(AbstractBuilder* builder)
:m_builder(builder) {}
~Director() {}
AbstractProduct* createComputer(string display, string host, string KeyBoard, string mouse)
{
m_builder->BuildDisplay(display);
m_builder->BuildHost(host);
m_builder->BuildKeyBoard(KeyBoard);
m_builder->BuildMouse(mouse);
return m_builder->getProduct();
}
private:
AbstractBuilder* m_builder;
};
int main()
{
//1. 创建电脑建造者
AbstractBuilder* Computer_Builder = new ComputerBuilder;
//2. 创建电脑建造者的 管理者
Director* pDcomp = new Director(Computer_Builder);
//3. 管理者指挥 建造者制造电脑产品
AbstractProduct* computerPro = pDcomp->createComputer("联想显示器", "外星人主机", "雷蛇键盘", "罗技鼠标");
//4. 电脑产品制造完成
computerPro->show();
//别忘了释放内存
delete Computer_Builder;
delete pDcomp;
delete computerPro;
return 0;
}
5.引用
2.5 万字详解:23 种设计模式 - 知乎 (zhihu.com)
C++设计模式:建造者模式(详解+案例代码)_Yuleo_的博客-CSDN博客