设计模式之生成器方法
一、生成器模式概念
Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。
简单来说就是封装一个复杂对象的构造过程,并允许按照步骤构造。
- 对象的创建:Builder模式是为对象的创建而设计的模式
- 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
- 关注对象创建的各部分的创建过程:不同的工厂(这里指builder生成器)对产品属性有不同的创建方法
适用场景:
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
生成器模式的结构:
代码及类图如下:
1.构造一个房屋,需要考虑是否有车库,是否有游泳池,是否有地下室,
是否有花园等,需要对诸多成员进行初始化工作。都写在构造函数里?
每种可能都创建一个新的类?2.相同的步骤需要能够产生不同的产品,例如
使用木头和玻璃盖出来的是普通住房。用黄金和水晶建造出来的是宫殿。解决方案:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
即将对象构造代码从产品中抽取出来,并将其放在一个名为“生成器”的独立对象中。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class SimpleHouse
{
public:
vector<string> m_parts;
void printParts() const{
cout << "Parts of the house: ";
for (const auto& part : m_parts){
cout << part << " " << endl;
}
cout << endl << "----------------" << endl;
}
};
class Builder
{
public:
virtual ~Builder() = default;
virtual void reset() = 0;
virtual void makeBaseHouse() = 0;
virtual void makeGarage() = 0;
virtual void makePool() = 0;
};
//施工队
class SimpleHouseBuilder : public Builder
{
private:
SimpleHouse* m_simplehouse;
public:
SimpleHouseBuilder(){
reset();
}
~SimpleHouseBuilder() override{
delete m_simplehouse;
}
void reset() override{
m_simplehouse = new SimpleHouse();
}
void makeBaseHouse() override{
m_simplehouse->m_parts.push_back("Base House");
}
void makeGarage() override{
m_simplehouse->m_parts.push_back("Garage");
}
void makePool() override{
m_simplehouse->m_parts.push_back("Swimming Pool");
}
SimpleHouse* getResult(){
SimpleHouse* result = m_simplehouse;
reset();
return result;
}
};
class Director
{
private:
Builder* m_builder;
public:
void setBuilder(Builder* builder){
m_builder = builder;
}
void makeSimpleHouse(){
m_builder->makeBaseHouse();
m_builder->makeGarage();
m_builder->makePool();
}
void makeFullFuncHouse(){
m_builder->makeBaseHouse();
m_builder->makeGarage();
m_builder->makePool();
}
};
void client(Director* director)
{
cout << "客户自己设计流程:" << endl;
SimpleHouseBuilder* builder = new SimpleHouseBuilder();
builder->makeBaseHouse();
builder->makeGarage();
SimpleHouse* simpleHouse = builder->getResult();
simpleHouse->printParts();
cout << "客户委托设计师设计流程:" << endl;
director->setBuilder(builder);
director->makeSimpleHouse();
SimpleHouse* simpleHouse2 = builder->getResult();
simpleHouse2->printParts();
delete builder;
delete simpleHouse;
}
int main()
{
Director director;
client(&director);
return 0;
}
二、生成器模式的优缺点
优点:
封装性很好:使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
扩展性很好:建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
有效控制细节风险:由于具体的建造者是独立的,因此可以对建造者过程逐步细化,而不对其他的模块产生任何影响。
将复杂对象的创建过程封装起来
允许对象通过几个步骤来创建,并且可以改变过程(工厂模式只有一个步骤)
只需指定具体生成器就能生成特定对象,隐藏类的内部结构
对象的实现可以被替换
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。