C++设计模式——建造者模式
概述
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
场景描述
现在有一个傻子要穿秋衣、秋裤、裤子和外套这四件衣服的场景,需要用代码来实现。我们脑子里第一个想法就是如下步骤:
1.创建一个傻子的类,里面有穿衣这个动作的接口函数。然后初始化一个对象。
2.分别创建秋衣、秋裤、裤子、外套的类,然后创建各自的对象。
3.客户端调用:使用傻子类创建出来的对象,做穿秋衣、秋裤、裤子、外套这四个动作。
4.大功告成。
但是现在问题来了,场景中是傻子穿衣服,他穿衣可能就先把裤子和外套穿上了,然后再穿秋衣秋裤。这种情况是很有可能出现的,那之前的办法很明显是有缺陷的。 另外一个问题,当这个傻子万一是流落民间的富二代,只是装疯卖傻呢?当他被家族发现后要继承家业了,总不可能穿的衣服和之前衣服类创建出来的衣服一样吧?所以再次用代码描述该场景的时候,需要改动的地方就比较多了。
建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。如此一来,我们用建造者模式来解决一下该问题。
类图描述
IdiotDressing: 该模式中用于被构造的复杂对象。里面有具体构造该对象的方法。
IBuilder: 抽象构造类,申明了构造复杂对象所需要的方法。
BuildBeggerDressing…:具体的构造类,用来狗仔复杂对象的不同表示。并且提供一个检索产品的接口。
Director: 负责产品的构造。(场景中保证穿衣顺序的对错关键)。
代码实现
//产品类
#ifndef IDIOTDRESS_H_
#define IDIOTDRESS_H_
#include <iostream>
class IdiotDressing
{
public:
void SetUnderWare(std::string strUnderWare)
{
m_strUnderWare = strUnderWare;
}
void SetBriefs(std::string strBriefs)
{
m_strBriefs = strBriefs;
}
void SetPants(std::string strPants)
{
m_strPants = strPants;
}
void SetCoat(std::string strCoat)
{
m_strCoat = strCoat;
}
std::string GetUnderWare()
{
return m_strUnderWare;
}
std::string GetBriefs()
{
return m_strBriefs;
}
std::string GetPants()
{
return m_strPants;
}
std::string GetCoat()
{
return m_strCoat;
}
private:
std::string m_strUnderWare;
std::string m_strBriefs;
std::string m_strPants;
std::string m_strCoat;
};
#endif
//建造者类
#ifndef BUILDER_H_
#define BUILDER_H_
#include "IdiotDressing.h"
class IBuilder
{
public:
virtual void BuildUnderware() = 0;
virtual void BuildBriefs() = 0;
virtual void BuildPants() = 0;
virtual void BuildCoat() = 0;
virtual IdiotDressing* GetIdiotDressing() = 0;
};
class BulidBeggerDressing : public IBuilder
{
public:
BulidBeggerDressing () {m_idiotDressing = new IdiotDressing();}
virtual void BuildUnderware(){ m_idiotDressing->SetUnderWare("脏的秋衣"); }
virtual void BuildBriefs() { m_idiotDressing->SetBriefs("破的秋裤"); }
virtual void BuildPants() { m_idiotDressing->SetPants("不合身的裤子"); }
virtual void BuildCoat() { m_idiotDressing->SetCoat("脏的外套"); }
virtual IdiotDressing* GetIdiotDressing(){ return m_idiotDressing; }
private:
IdiotDressing* m_idiotDressing;
};
class BuildBossDressing : public IBuilder
{
public:
BuildBossDressing () {m_idiotDressing = new IdiotDressing();}
virtual void BuildUnderware() { m_idiotDressing->SetUnderWare("干净的秋衣"); }
virtual void BuildBriefs() { m_idiotDressing->SetBriefs("合身的秋裤"); }
virtual void BuildPants() { m_idiotDressing->SetPants("名牌的西裤"); }
virtual void BuildCoat() { m_idiotDressing->SetCoat("名牌的西装"); }
virtual IdiotDressing* GetIdiotDressing(){ return m_idiotDressing; }
private:
IdiotDressing* m_idiotDressing;
};
#endif
//指挥者类
#ifndef DIRECTOR_H_
#define DIRECTOR_H_
#include "Builder.h"
class Director
{
public:
//实现建造流程
void Dressing(IBuilder* builder)
{
builder->BuildUnderware();
builder->BuildBriefs();
builder->BuildPants();
builder->BuildCoat();
}
};
#endif
#include <iostream>
#include "Builder.h"
#include "Director.h"
using namespace std;
#ifndef DELETE_OBJECT
#define DELETE_OBJECT(Obj) \
{\
if (Obj) \
{\
delete (Obj); \
(Obj)=NULL;\
}\
}
#endif
int main()
{
//创建两个建造者
IBuilder* pBeggerBuilder = new BulidBeggerDressing();
IBuilder* pBossBuilder = new BuildBossDressing();
//创建一个指挥者,并且创建相应的产品表现。
Director* pDirector = new Director();
pDirector->Dressing(pBeggerBuilder);
pDirector->Dressing(pBossBuilder);
IdiotDressing* pBeggerDress = pBeggerBuilder->GetIdiotDressing();
IdiotDressing* pBossDress = pBossBuilder->GetIdiotDressing();
cout << "Begger Dressing" << endl;
cout << "Underware:" << pBeggerDress->GetUnderWare().c_str() << endl;
cout << "Briefs:" << pBeggerDress->GetBriefs().c_str() << endl;
cout << "Pants:" << pBeggerDress->GetPants().c_str() << endl;
cout << "Coat:" << pBeggerDress->GetCoat().c_str() << endl<<endl<<endl;
cout << "Boss Dressing" << endl;
cout << "Underware:" << pBossDress->GetUnderWare().c_str() << endl;
cout << "Briefs:" << pBossDress->GetBriefs().c_str() << endl;
cout << "Pants:" << pBossDress->GetPants().c_str() << endl;
cout << "Coat:" << pBossDress->GetCoat().c_str() << endl;
DELETE_OBJECT(pBeggerBuilder);
DELETE_OBJECT(pBossBuilder);
DELETE_OBJECT(pDirector);
DELETE_OBJECT(pBeggerDress);
DELETE_OBJECT(pBossDress);
return 0;
}
优缺点
优点:
封装性好,易于扩展,如果有新的表现形式,只需要实现一个builder接口即可。符合开闭原则
对复杂对象的建造流程可控。
缺点:
- 只针对同类产品的建造。有局限性。
适用场景
适用于对象内部比较复杂的复杂对象的构建。