本类型的最后一个模式,最后一节进行总结。
1. 情景与意图
假设我们现在需要见一个房子,建房子的过程都是一样的,比如:先确定户主,建造地基,建造墙壁,建造屋顶。所有种类的房屋建造顺序都如上所示。但是每个房子的具体步骤肯定是不一样的。这其中我们可以看到变化的就是具体的建造步骤,稳定的就是整体的建造顺序。
在日常开发中,可能会有一个复杂对象的创建工作,其通常由各个子步骤用一定的算法构成,由于需求的变化,这个复杂对象的子步骤部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
我们提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?——建造者模式
2. 建造者模式
将一个复杂的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同(变化)的表示。建造者模式或者说构建起模式,构建过程就是设计模式一直强调的就是依赖稳定,不同的创建表示就是变化。
看到后面的实现过程,可能心中会有一个疑问,建造者模式和模板方法模式有什么区别? 这个问题其实在实现的过程中也许就已经有答案,我会在最后进行做出自己的解释欢迎探讨。
3. 构建器建造房子
下面建造两种房子,就是水晶房子和石头房子。首先我们抽象一个房子;
class DPAbstractHouse {
public:
virtual void showMessage();
virtual void setWallMessage(std::string message) = 0;
virtual void setWindowsMessage(std::string message) = 0;
virtual void setRoofMessage(std::string message) = 0;
virtual void setFoundationMessage(std::string message) = 0;
virtual void setHostName(std::string hostName) = 0;
virtual void setHouseName(std::string houseName) = 0;
protected:
std::string _hostName; // 户主
std::string _houseName; // 名字
std::string _wallMessage;
std::string _windowsMessage;
std::string _roofMessage;
std::string _foundationMessage;
};
然后具体两个类。
class DPStoneHouse :public DPAbstractHouse {
public:
/*同上public的方法*/
};
class DPCrystalHouse :public DPAbstractHouse {
public:
/**/
};
然后抽象构建器:
class DPAbstractBuilder {
public:
// 这些函数主要为了体现创建对象的流程,表示复杂性
virtual void setHostName(std::string hostName) = 0;
virtual bool buildFoundation() = 0;
virtual bool buildTheWall() = 0;
virtual bool buildTheRoof() = 0;
virtual DPAbstractHouse* getHouse();
protected:
DPAbstractHouse* _pHouse;
};
具体构建器:
class DPStoneHouseBuilder : public DPAbstractBuilder {
public:
DPStoneHouseBuilder();
virtual void setHostName(std::string hostName);
virtual bool buildFoundation();
virtual bool buildTheWall();
virtual bool buildTheRoof();
protected:
};
class DPCrystalHouseBuilder : public DPAbstractBuilder {
public:
DPCrystalHouseBuilder();
virtual void setHostName(std::string hostName);
virtual bool buildFoundation();
virtual bool buildTheWall();
virtual bool buildTheRoof();
};
最后是构建指挥,或者构建中心:
// .h
class DPHouseDirector {
DPAbstractBuilder* _houseBuilder;
public:
DPHouseDirector(DPAbstractBuilder* houseBuilder);
DPAbstractHouse* houseDirector(std::string host);
};
// .cpp
DPHouseDirector::DPHouseDirector(DPAbstractBuilder* houseBuilder) {
_houseBuilder = houseBuilder;
}
// 重要的就是这一步,看着很像模板方法模式
// 所以有同学会产生疑问
DPAbstractHouse* DPHouseDirector::houseDirector(std::string host) {
if (host.size() <= 0) {
return nullptr;
}
_houseBuilder->setHostName(host);
if (_houseBuilder->buildFoundation()) {
_houseBuilder->buildTheWall();
_houseBuilder->buildTheRoof();
}
return _houseBuilder->getHouse();
}
最后我们使用一下:
int main() {
DPAbstractBuilder* stoneBuilder = new DPStoneHouseBuilder();
DPHouseDirector* director = new DPHouseDirector(stoneBuilder);
DPAbstractHouse* stoneHouse = director->houseDirector(std::string("王二麻子"));
stoneHouse->showMessage();
return 0;
}
4. 大总结
首先解决一开始的问题:建造者模式和模板方法模式有什么区别?
在刚才的模板方法模式属于组件协作类型,而建造者模式属于对象创建类型。两者相同的地方在于稳定的部分都是一个固定的步骤。而模板方法模式的固定步骤,主要是针对不同的子类而有不同的表现形式;在建造者模式中,固定地方是建造对象的步骤,变化的地方就是具体的创建逻辑,从而创建不同的对象。
从前面的【工厂模式系列】【原型模式】到现在的【建造者模式】都属于统一类型——对象创建类型模式。
通过“对象创建” 模式绕开new,来避免对象创建(new)过程 中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它 是接口抽象之后的第一步工作。
建造者模式源代码【建造者模式C++源码】