定义:
即生成器模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
示例一:建造者模式(通用版)
1. 类图11-4
2. 类图说明:
在建造者模式中,有如下4个角色:
Product 产品类: 通常是实现了模板方法模式,也就是有模板方法和基本方法。例子中的 BenzModel 和 BMWModel就属于产品类。
Builder 抽象建造者:规范产品的组件,一般是由子类实现。例子中的CarBuilder 就属于抽象建造者。
ConcreteBuilder 具体建造者:实现抽象类定义的所有方法,并且翻译一个组建好的对象。例子中的 BenzBuilder 和 BMWBuilder 就属于具体建造者。
Director 导演类:负责安排已有模块的顺序,然后告诉Builder开始建造。
3. 代码清单11-4:
// ********** 4.建造者模式的通用版本 ,代码清单11-4:***************//
class Product
{
public:
void doSomething(){qDebug() << "***";}
};
class Builder
{
public:
virtual void setPart() = 0;
virtual Product* buildProduct() = 0;
};
class ConcreteProduct: public Builder
{
public:
ConcreteProduct() {this->m_product = new Product();}
~ConcreteProduct(){delete this->m_product;}
void setPart(){} //产品类内的逻辑处理
Product* buildProduct()
{
return this->m_product;
}
private:
Product* m_product;
};
class Director
{
public:
Director() {this->m_builder = new ConcreteProduct();}
~Director(){delete this->m_builder;}
Product* getAProduct()
{
this->m_builder->setPart();
Product* product = dynamic_cast<Product*>(this->m_builder->buildProduct());
return product;
}
private:
ConcreteProduct *m_builder;
};
int main ()
{
Director director;
director.getAProduct()->doSomething();
return 0;
}
示例二:汽车模型扩展,根据不同的产品,执行任务的顺序不同
1. 类图11-1
2. 类图说明:
在CarModel 中定义了一个 setSequence 方法,车辆模型的动作如何排布在 ArrayList 中定义。然后 run() 方法根据 sequence 定义的顺序完成指定的顺序动作
3.代码清单11-1:
********** 1.车辆模型扩展 ,代码清单11-1:***************//
enum ESequence
{
EStart ,
EStop ,
EAlarm ,
EEnginBoom
};
class CarModel
{
protected:
virtual void start() = 0;
virtual void stop() = 0;
virtual void alarm() = 0;
virtual void enginBoom() = 0;
public:
void setSequence(QList<ESequence> list){this->m_list = list;}
void run()
{
QList<ESequence>::const_iterator iter = this->m_list.begin();
while(iter != this->m_list.end())
{
switch (*iter)
{
case EStart:
this->start();
break;
case EStop:
this->stop();
break;
case EAlarm:
this->alarm();
break;
case EEnginBoom:
this->enginBoom();
break;
};
++iter;
}
}
private:
QList<ESequence> m_list;
};
class BenzModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BenzModel : start";}
virtual void stop() {qDebug() << "BenzModel : stop";}
virtual void alarm() {qDebug() << "BenzModel : alarm";}
virtual void enginBoom() {qDebug() << "BenzModel : enginBoom";}
};
class BMWModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BMWModel : start";}
virtual void stop() {qDebug() << "BMWModel : stop";}
virtual void alarm() {qDebug() << "BMWModel : alarm";}
virtual void enginBoom() {qDebug() << "BMWModel : enginBoom";}
};
int main()
{
CarModel *benz = new BenzModel();
QList<ESequence> list;
list.clear();
list.push_back(EEnginBoom);
list.push_back(EAlarm);
list.push_back(EStart);
list.push_back(EStop);
benz->setSequence(list);
benz->run();
delete benz;
return 0;
}
示例三:汽车模型扩展,增加需求:动作执行顺序可以随意调整
1. 类图11-2
2. 类图说明:
增加了一个CarBuilder 抽象类,用来组装各个车模,需要什么类型什么顺序的车辆模型,都由相关的子类完成。
3. 代码清单11-2:
********** 2.车辆模型扩展 ,代码清单11-2:***************//
enum ESequence
{
EStart ,
EStop ,
EAlarm ,
EEnginBoom
};
class CarModel
{
protected:
virtual void start() = 0;
virtual void stop() = 0;
virtual void alarm() = 0;
virtual void enginBoom() = 0;
public:
void setSequence(QList<ESequence> list){this->m_list = list;}
void run()
{
QList<ESequence>::const_iterator iter = this->m_list.begin();
while(iter != this->m_list.end())
{
switch (*iter)
{
case EStart:
this->start();
break;
case EStop:
this->stop();
break;
case EAlarm:
this->alarm();
break;
case EEnginBoom:
this->enginBoom();
break;
};
++iter;
}
}
private:
QList<ESequence> m_list;
};
class BenzModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BenzModel : start";}
virtual void stop() {qDebug() << "BenzModel : stop";}
virtual void alarm() {qDebug() << "BenzModel : alarm";}
virtual void enginBoom() {qDebug() << "BenzModel : enginBoom";}
};
class BMWModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BMWModel : start";}
virtual void stop() {qDebug() << "BMWModel : stop";}
virtual void alarm() {qDebug() << "BMWModel : alarm";}
virtual void enginBoom() {qDebug() << "BMWModel : enginBoom";}
};
class CarBuilder
{
public:
virtual void setSequence(QList<ESequence> list) = 0;
virtual CarModel* getCarModel() = 0;
};
class BenzBuilder: public CarBuilder
{
public:
BenzBuilder() {m_benz = new BenzModel();}
~BenzBuilder() {delete m_benz;}
virtual void setSequence(QList<ESequence> list){this->m_benz->setSequence(list);}
virtual CarModel* getCarModel()
{
CarModel *car = dynamic_cast<CarModel*>(m_benz);
return car;
}
private:
BenzModel *m_benz;
};
class BMWBuilder: public CarBuilder
{
public:
BMWBuilder() {m_bmw = new BMWModel();}
~BMWBuilder() {delete m_bmw;}
virtual void setSequence(QList<ESequence> list){this->m_bmw->setSequence(list);}
virtual CarModel* getCarModel()
{
CarModel *car = dynamic_cast<CarModel*>(m_bmw);
return car;
}
private:
BMWModel *m_bmw;
};
int main()
{
//benz
QList<ESequence> list;
list.clear();
list.push_back(EEnginBoom);
list.push_back(EAlarm);
list.push_back(EStart);
list.push_back(EStop);
BenzBuilder benzBuilder;
BenzModel *benz;
benzBuilder.setSequence(list);
benz = dynamic_cast<BenzModel*>(benzBuilder.getCarModel());
benz->run();
//bmw
QList<ESequence> list2;
list2.clear();
list2.push_back(EStop);
list2.push_back(EAlarm);
list2.push_back(EStart);
list2.push_back(EEnginBoom);
BMWBuilder bmwBuilder;
BMWModel *bmw;
bmwBuilder.setSequence(list2);
bmw = dynamic_cast<BMWModel*>(bmwBuilder.getCarModel());
bmw->run();
return 0;
}
示例四:汽车模型扩展,增加需求:根据不同的给定顺序进行生产
1. 类图11-3
2. 类图说明:
增加了一个 Director 类,负责按照指定的顺序生产模型
3. 结构说明:
getABenzModel 方法:组件出A型号的奔驰车模型,其过程为只有start 、stop ;没有engineboom 、alarm 。
getBBenzModel 方法:组件出B型号的奔驰车模型,其过程为 engineboom → start → stop ;没有alarm 。
getCBMWModel 方法:组件出C型号的宝马车模型,其过程为 alarm → start → stop ,没有engineboom
getDBMWModel 方法:组件出D型号的宝马车模型,其过程为 start ; 没有engineboom 、alarm 、stop
3. 代码清单11-3:
********** 3.车辆模型扩展 ,代码清单11-3:***************//
enum ESequence
{
EStart ,
EStop ,
EAlarm ,
EEnginBoom
};
class CarModel
{
protected:
virtual void start() = 0;
virtual void stop() = 0;
virtual void alarm() = 0;
virtual void enginBoom() = 0;
public:
void setSequence(QList<ESequence> list){this->m_list = list;}
void run()
{
QList<ESequence>::const_iterator iter = this->m_list.begin();
while(iter != this->m_list.end())
{
switch (*iter)
{
case EStart:
this->start();
break;
case EStop:
this->stop();
break;
case EAlarm:
this->alarm();
break;
case EEnginBoom:
this->enginBoom();
break;
};
++iter;
}
}
private:
QList<ESequence> m_list;
};
class BenzModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BenzModel : start";}
virtual void stop() {qDebug() << "BenzModel : stop";}
virtual void alarm() {qDebug() << "BenzModel : alarm";}
virtual void enginBoom() {qDebug() << "BenzModel : enginBoom";}
};
class BMWModel:public CarModel
{
protected:
virtual void start() {qDebug() << "BMWModel : start";}
virtual void stop() {qDebug() << "BMWModel : stop";}
virtual void alarm() {qDebug() << "BMWModel : alarm";}
virtual void enginBoom() {qDebug() << "BMWModel : enginBoom";}
};
class CarBuilder
{
public:
virtual void setSequence(QList<ESequence> list) = 0;
virtual CarModel* getCarModel() = 0;
};
class BenzBuilder: public CarBuilder
{
public:
BenzBuilder() {m_benz = new BenzModel();}
~BenzBuilder() {delete m_benz;}
virtual void setSequence(QList<ESequence> list){this->m_benz->setSequence(list);}
virtual CarModel* getCarModel()
{
CarModel *car = dynamic_cast<CarModel*>(m_benz);
return car;
}
private:
BenzModel *m_benz;
};
class BMWBuilder: public CarBuilder
{
public:
BMWBuilder() {m_bmw = new BMWModel();}
~BMWBuilder() {delete m_bmw;}
virtual void setSequence(QList<ESequence> list){this->m_bmw->setSequence(list);}
virtual CarModel* getCarModel()
{
CarModel *car = dynamic_cast<CarModel*>(m_bmw);
return car;
}
private:
BMWModel *m_bmw;
};
//导演类
class Director
{
public:
Director()
{
m_benzBuilder = new BenzBuilder();
m_bmwBuilder = new BMWBuilder();
}
~Director()
{
delete this->m_benzBuilder;
delete this->m_bmwBuilder;
}
BenzModel* getABenzModel()
{
this->m_list.clear();
this->m_list.push_back(EStart);
this->m_list.push_back(EStop);
this->m_benzBuilder->setSequence(this->m_list);
BenzModel *model = dynamic_cast<BenzModel*>(m_benzBuilder->getCarModel());
return model;
}
BenzModel* getBBenzModel()
{
this->m_list.clear();
this->m_list.push_back(EEnginBoom);
this->m_list.push_back(EStart);
this->m_list.push_back(EStop);
this->m_benzBuilder->setSequence(this->m_list);
BenzModel *model = dynamic_cast<BenzModel*>(m_benzBuilder->getCarModel());
return model;
}
BMWModel* getCBMWModel()
{
this->m_list.clear();
this->m_list.push_back(EAlarm);
this->m_list.push_back(EStart);
this->m_list.push_back(EStop);
this->m_bmwBuilder->setSequence(this->m_list);
BMWModel *model = dynamic_cast<BMWModel*>(m_bmwBuilder->getCarModel());
return model;
}
BMWModel* getDBMWModel()
{
this->m_list.clear();
this->m_list.push_back(EStart);
this->m_bmwBuilder->setSequence(this->m_list);
BMWModel *model = dynamic_cast<BMWModel*>(m_bmwBuilder->getCarModel());
return model;
}
private:
QList<ESequence> m_list;
BenzBuilder *m_benzBuilder;
BMWBuilder *m_bmwBuilder;
};
int main()
{
Director director;
//生产2辆A类型奔驰车
for (int i = 0; i < 2; ++i){director.getABenzModel()->run();}
//3辆B类型奔驰车
for (int i = 0; i < 3; ++i){director.getBBenzModel()->run();}
//4辆C类型宝马车
for (int i = 0; i < 4; ++i){director.getCBMWModel()->run();}
return 0;
}
五、建造者模式的应用
1. 优点:
- 封装性。使用建造者模式可以使客户端不必知道产品内部组成的细节,如例子中我们不关心每一个具体模型的内部是怎样实现的,产生的对象类型就是CarModel。
- 建造者独立,容易扩展。BenzBuilder 和 BMWBuilder 是相互独立的,对系统的扩展非常有利。
- 便于控制细节风险。由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他模块产生任何影响。
2. 使用场景:
- 相同的方法,不同的执行顺序,产生不同的时间结果时。
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能。
- 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时。该场景只是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉。
3. 注意事项:
建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大的不同。
参考文献《秦小波. 设计模式之禅》(第2版) (华章原创精品) . 机械工业出版社