设计模式学习笔记(Build模式)

来源:互联网 发布:功能分析和数据分析 编辑:程序博客网 时间:2024/05/15 08:50

一、Build模式的作用

通过Build模式可以利用同一个创建过程创建出不同的对象,即同样的构建过程可以创建不同的表示。并且将具体的构建过程向客户隐藏。 

Build模式的参与者有Builder、ConcreteBuild、Dirctor以及Product。构建指的就是生产一个产品的步骤(Dirctor),表示就是每个产品部分的具体实现(ConcreteBuild),通过Director封装步骤,通过Builder封装产品部分的实现[具体实现在ConcreteBuild类中],再把他两分离表示,最后被构造的复杂对象就是Product类对象(主角)

二、为什么需要Build模式

那我们为什么不多写几个构造函数,通过不同参数创建具有不同属性的对象?

如果这样做,每次要新增一种对象的表示,我们都需要在之前的类中添加一个构造函数,从可读性和设计上来看,都非常臃肿,不符合面向对象的封闭原则

那能不能利用对象所在类中的set函数,每次新建对象通过进行不同的set来得到具有不同属性的对象?

这样做虽然满足了封闭原则,但是却完全属于面向过程的设计,没有将对象的构建与表示分离,并且如果要设置的参数过多则不好管理

而Build模式将一个复杂对象构建与它的表示分离,封装和抽象了每个步骤的实现,向客户隐藏了产品内部的实现。使得可以利用同样的构建过程创建出不同的表示。

三、使用场景

建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

抽象工厂模式(AbtractFactory)解决的是“系列对象”的需求变化,Builder模式解决的是“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。

需要隐藏产品的具体建造过程。

四、缺点

使用Builder模式是增加了代码量

五、实例

比如:将大象装进冰箱分为3步:A(打开冰箱门)、B(将大象放进去)、C(关上冰箱门)。通过A->B->C三个步骤完成将大象装进冰箱这个操作。但是问题来了,如果我们想将大象装进不同品牌不同型号的冰箱怎么办?不同品牌不同型号的冰箱也许开门的具体操作不同,关门的具体操作不同等等.....

这时,Build模式就起作用了!Dirctor表示了这三个步骤;Build类表示了每一个操作(但是没有具体的实现);ConcreteBuild是具体的实现(继承Build);

Dirctor部分:

Director.h#ifndef _DIRECTOR_H_#define _DIRECTOR_H_#include "ConcreteBuilder.h"class Director{public:Director(Builder* builder);~Director();void construct();private:Builder* curBuilder;};#endif 
Director.cpp#include "Director.h"Director::Director(Builder* builder){     curBuilder = builder;}Director::~Director(){}void Director::construct(){if (!curBuilder)return;curBuilder->createProduct();curBuilder->buildPartA(1);//A(打开冰箱门)curBuilder->buildPartB(2);//B(将大象放进去)curBuilder->buildPartC(3);//C(关上冰箱门)}
Build部分:[这里也可以不将Build变为纯虚类,使客户只对他们感兴趣的操作进行重定义]

class Builder{public:Builder();virtual ~Builder();virtual void createProduct() = 0;virtual void buildPartA(int param) = 0;virtual void buildPartB(int param) = 0;virtual void buildPartC(int param) = 0;virtual Product* getProduct() = 0;};
ConcreteBuilder部分:每个步骤的具体实现(不同品牌不同型号冰箱的每个步骤的具体操作在这里修改)
class ConcreteBuilder: public Builder{public:ConcreteBuilder();~ConcreteBuilder();void createProduct();void buildPartA(int param);//针对不同的品牌不同的型号,可以有不同的实现(例如有的冰箱没有门,则该函数内容为空)void buildPartB(int param);void buildPartC(int param);Product* getProduct();private:Product* curProduct;};

ConcreteBuilder::ConcreteBuilder():curProduct(NULL){}ConcreteBuilder::~ConcreteBuilder(){}void ConcreteBuilder::createProduct(){cout<<"完成一个表演";curProduct = new Product();}void ConcreteBuilder::buildPartA(int param){cout<<"将A牌冰箱门打开";curProduct->setPartA(param);}void ConcreteBuilder::buildPartB(int param){cout<<"将大象装进A牌冰箱";curProduct->setPartB(param);}void ConcreteBuilder::buildPartC(int param){cout<<"将A牌冰箱门关闭\n");curProduct->setPartC(param);}Product* ConcreteBuilder::getProduct()//这里涉及到指针对象的释放问题,由于只是伪代码,不详细展开.{return curProduct;}
Product
class Product{public:Product();~Product();void setPartA(int param);void setPartB(int param);void setPartC(int param);void show();private:int partA;int partB;int partC;};
Product::Product(){}Product::~Product(){}void Product::setPartA(int param){partA = param;}void Product::setPartB(int param){partB = param;}void Product::setPartC(int param){partC = param;}void Product::show(){       cout<<"partA = "<<partA<<"partB ="<<partB<<"partC = "<<partC;}

具体的调用:

int main(){Builder* builder = new ConcreteBuilder();Director* director = new Director(builder);director->construct();Product* product = builder->getProduct();product->show();return 0;}



原创粉丝点击