Chapter7—建造者模式
建造者模式
1 概念
建造者模式是指将一个复杂对象的构造与它的表示分离,展现了对象内部创建的过程和细节,将创建对象的各个细节按照一定的顺序组装起来,形成一个完整的对象。建造者模式注重创建对象的过程,返回创建对象的结果。
2 意图(Intent)
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
3 动机(Motivate)
在软件系统中,有时候面临一个"复杂对象"的创建工作,其通常由各个部分的子对象用一定算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合到一起的算法却相对稳定。如何应对种变化呢?如何提供一种"封装机制"来隔离出"复杂对象的各个部分"的变化,从而保持系统中的"稳定构建算法"不随需求的改变而改变。其抽象的位置在于对象创建的细节步骤。
4 类图结构
5 角色定义
- Builder(建造者):为创建一个Product对象的各个部件指定抽象接口,定义了构成产品的各个组件的构建标准,通常有多个步骤。
- ConcreteBuilder(建造者实现):具体建造者,可以有多种实现,负责产品的组装但不包含整体建造逻辑。
- Product(产品):复杂的产品类,构建过程相对复杂,需要其他组件组装而成。
- Director(指导者):持有建造者接口引用的指导者类,指导建造者按一定的逻辑进行建造。
6 程序示例
机器人产品
类图关系
class Robot
{
public:Robot() = default;~Robot() = default;public:void SetHead(const string& strHead);void SetBody(const string& strBody);void SetHand(const string& strHand);void SetFeet(const string& strFeet);void Show();private:string m_strHead;string m_strBody;string m_strHand;string m_strFeet;
};void Robot::SetHead(const string &strHead)
{m_strHead = strHead;
}void Robot::SetBody(const string &strBody)
{m_strBody = strBody;
}void Robot::SetHand(const string &strHand)
{m_strHand = strHand;
}void Robot::SetFeet(const string &strFeet)
{m_strFeet = strFeet;
}void Robot::Show()
{qDebug() << "Head =" << m_strHead.c_str();qDebug() << "Body =" << m_strBody.c_str();qDebug() << "Hand =" << m_strHand.c_str();qDebug() << "Feet =" << m_strFeet.c_str();
}
机器人建造者抽象类
class BaseBuildRobot
{
public:BaseBuildRobot();virtual ~BaseBuildRobot();public:virtual void BuildHead() = 0;virtual void BuildBody() = 0;virtual void BuildHand() = 0;virtual void BuildFeet() = 0;std::shared_ptr<Robot> GetRobot();protected:std::shared_ptr<Robot> m_spRobot;
};BaseBuildRobot::BaseBuildRobot()
{m_spRobot = std::make_shared<Robot>();
}BaseBuildRobot::~BaseBuildRobot()
{// ...
}std::shared_ptr<Robot> BaseBuildRobot::GetRobot()
{return m_spRobot;
}
机器人建造者具体类
class BuildKukaRobot : public BaseBuildRobot
{
public:BuildKukaRobot() = default;~BuildKukaRobot() = default;public:void BuildHead() override;void BuildBody() override;void BuildHand() override;void BuildFeet() override;
};void BuildKukaRobot::BuildHead()
{m_spRobot->SetHead("Kuka机器人头部");
}void BuildKukaRobot::BuildBody()
{m_spRobot->SetBody("Kuka机器人身体");
}void BuildKukaRobot::BuildHand()
{m_spRobot->SetHand("Kuka机器人手部");
}void BuildKukaRobot::BuildFeet()
{m_spRobot->SetFeet("Kuka机器人脚部");
}
指导者类
class Director
{
public:Director(const std::shared_ptr<BaseBuildRobot>& spRobotBuilder);~Director() = default;public:void SetRobotBuilder(const std::shared_ptr<BaseBuildRobot>& spRobotBuilder);std::shared_ptr<Robot> Direct(); // 指导创建private:std::shared_ptr<BaseBuildRobot> m_spRobotBuilder;
};Director::Director(const std::shared_ptr<BaseBuildRobot> &spRobotBuilder) : m_spRobotBuilder(spRobotBuilder)
{// ...
}void Director::SetRobotBuilder(const std::shared_ptr<BaseBuildRobot> &spRobotBuilder)
{m_spRobotBuilder = spRobotBuilder;
}std::shared_ptr<Robot> Director::Direct()
{m_spRobotBuilder->BuildHead();m_spRobotBuilder->BuildBody();m_spRobotBuilder->BuildHand();m_spRobotBuilder->BuildFeet();return m_spRobotBuilder->GetRobot();
}
客户端测试程序
void ClientTest()
{std::shared_ptr<BaseBuildRobot> spBuildRobot = std::make_shared<BuildKukaRobot>();std::unique_ptr<Director> upDirector = std::make_unique<Director>(spBuildRobot);std::shared_ptr<Robot> spRobot = upDirector->Direct();spRobot->Show();
}
程序输出
Head = Kuka机器人头部
Body = Kuka机器人身体
Hand = Kuka机器人手部
Feet = Kuka机器人脚部
我们在实例中使用了一些C++的智能指针,方便内存的管理。
建筑施工的示例
类图结构
建筑物类
/*** @brief 建筑物类*/
class Building
{
public:Building() = default;~Building() = default;public:void SetBasement(const string& strBasement); // 地基void SetWall(const string& strWall); // 墙体void SetRoof(const string& strRoof); // 屋顶void Show();private:vector<string> m_vecBuildingComponents;
};void Building::SetBasement(const string &strBasement)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strBasement);
}void Building::SetWall(const string &strWall)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strWall);
}void Building::SetRoof(const string &strRoof)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strRoof);
}void Building::Show()
{for (auto& strComponent : m_vecBuildingComponents)qDebug() << strComponent.c_str();
}
施工方基类和别墅施工方、多层公寓施工方类
/*** @brief 施工方接口**/
class BaseBuilder
{
public:BaseBuilder() = default;virtual ~BaseBuilder() = default;public:virtual void BuildBasement() = 0;virtual void BuildWall() = 0;virtual void BuildRoof() = 0;virtual Building* GetBuilding() = 0;
};/*** @brief 别墅施工方**/
class HouseBuilder: public BaseBuilder
{
public:HouseBuilder();~HouseBuilder() = default;public:void BuildBasement() override;void BuildWall() override;void BuildRoof() override;Building* GetBuilding() override;private:Building* m_pHouseBuilding;
};HouseBuilder::HouseBuilder(): m_pHouseBuilding(new Building())
{// ...
}void HouseBuilder::BuildBasement()
{m_pHouseBuilding->SetBasement("╬╬╬╬╬╬╬╬╬╬╬╬");
}void HouseBuilder::BuildWall()
{m_pHouseBuilding->SetWall("|田|田|田|田|");
}void HouseBuilder::BuildRoof()
{m_pHouseBuilding->SetRoof("/◥▇▇▇▇◣");
}Building *HouseBuilder::GetBuilding()
{return m_pHouseBuilding;
}/*** @brief 多层公寓施工方**/
class ApartmentBuilder: public BaseBuilder
{
public:ApartmentBuilder();~ApartmentBuilder() = default;public:void BuildBasement() override;void BuildWall() override;void BuildRoof() override;Building* GetBuilding() override;private:Building* m_pApartmentBuilding;
};ApartmentBuilder::ApartmentBuilder(): m_pApartmentBuilding(new Building())
{// ...
}void ApartmentBuilder::BuildBasement()
{m_pApartmentBuilding->SetBasement("╚═══════════╝");
}void ApartmentBuilder::BuildWall()
{for (int i = 0; i != 8; ++i)m_pApartmentBuilding->SetWall("║□□□□□□□□□□□║");
}void ApartmentBuilder::BuildRoof()
{m_pApartmentBuilding->SetRoof("╔═══════════╗");
}Building *ApartmentBuilder::GetBuilding()
{return m_pApartmentBuilding;
}
工程总监类,也就是指导者
/*** @brief 工程总监类**/
class Director
{
public:Director(BaseBuilder* pBuilder);~Director() = default;public:void SetBuilder(BaseBuilder* pBuilder);Building* Direct(); // 指导创建private:BaseBuilder* m_pBuilder;
};Director::Director(BaseBuilder* pBuilder): m_pBuilder(pBuilder)
{// ...
}void Director::SetBuilder(BaseBuilder* pBuilder)
{m_pBuilder = pBuilder;
}Building* Director::Direct()
{m_pBuilder->BuildBasement();m_pBuilder->BuildWall();m_pBuilder->BuildRoof();return m_pBuilder->GetBuilding();
}
测试函数
void ClientTest()
{BaseBuilder* pHouseBuilder = new HouseBuilder();BaseBuilder* pApartmentBuilder = new ApartmentBuilder();Director* pDirector = new Director(pHouseBuilder);Building* pHouseBuilding = pDirector->Direct();pDirector->SetBuilder(pApartmentBuilder);Building* pApartmentBuilding = pDirector->Direct();pHouseBuilding->Show();pApartmentBuilding->Show();// 释放指针内存delete pDirector;delete pHouseBuilder;delete pApartmentBuilder;delete pHouseBuilding;delete pApartmentBuilding;
}
7 思考小结
建造者模式实现了具体的建造过程与建造的产品对象的分离,将产品对象的组装细节进行隐藏,用户如果要定义一个新的产品,只需要再构造一个具体建造过程的派生类对象。建造者模式一般用于比较复杂的对象构建,因为复杂对象的构建需要专业的建造团队,建造标准的确立让产品趋向多样化,其建造工艺可以交给多位建造者去各显其长,而建造工序则交由工程总监去全局把控,把"变"与"不变"分开,使"工艺多样化"和"工序标准化",最终实现通过相同的构建过程生产出不同产品,这也是建造者模式要达成的目标。