设计模式学习总结:(9)建造者模式

builder模式,即建造者模式,和前面的工厂一样都是用于解决对象创建的问题。

意图:

将一个复杂对象的构建与它的实现分离,使得同样的构建过程可以创建不同的表示。

问题抛出,什么是复杂对象的构建过程。

代码:

class Car
{
public:
    void Init() //构造
    {
        this->designPrototype();
        for (int i = 0; i < 4; i++)
        {
            this->wheelInstall(i);
        }
        this->smartInit();
        this->systemTest();
    }
protected:
    virtual void designPrototype()=0;
    virtual void wheelInstall(int)=0;
    virtual void smartInit()=0;
    virtual void systemTest()=0;
};

这里没有把构造过程放进构造函数,是因为构造函数中无法动态绑定this,原因:子类构造函数会先调用父类的构造函数,而父类构造函数执行到动态绑定的语句时,与通过this的虚函数表(如果不知道要研究下了)查询相应的函数,而此时子类还未初始化完成,所以会抛出错误。

init()为对象构建过程,在这里该过程具有稳定性。

class Ferrari :public Car
{
    string _name = "Ferrari";
    virtual void designPrototype();
    virtual void wheelInstall(int);
    virtual void smartInit();
    virtual void systemTest();
public:
    void sayName()
    {
        cout << _name << endl;
    }
    Ferrari(){ Car::Init(); }
};
void Ferrari::designPrototype()
{
    this->_name = "Ferrari";
    cout << "设计汽车原型中。。。" << endl;
    //实际实现代码。。。
    cout << "原型设计完毕,准备进入下一阶段" << endl;
}
void Ferrari::wheelInstall(int time)
{
    cout << "初始化第" << time << "个轮子" << endl;
    cout << "组装中" << endl;
    //实现代码,比如轮子类
    cout << "轮子组装完毕,进入下一阶段" << endl;

}
void Ferrari::smartInit()
{
    cout << "机动层初始化" << endl;
    cout << "机动层正常,进入下一阶段" << endl;
}
void Ferrari::systemTest()
{
    cout << "汽车性能测试" << endl;
    cout << "安全测试" << endl;
    cout << "试跑正常" << endl;
    cout << "构建成功" << endl;
}

测试:

好像,这样子已经可以很大程度上满足我们的需求了,而且结果似乎很完美。

builder模式的结构是怎么样的呢。

结构图:

其实就是把我们上面的一个大类,分成了director,builder,和product(它本身),director复制init工作,builder复制每一个小步骤,于是director是一个稳定的类,car的构建过程是相对稳定的,而builder是变化莫测的,因为它的每一步都可能是变化的,至少我们上面的代码,就是是轮子组装这一块,如果我们还有一个轮子类,那么我还是想象,法拉利和宝马的轮子应该是不一样的,轮子构造过程应该也可以是变化的,当然这种假设是抽象的,只是为了迎合这样一个模式,完全不用太较真。

所以用builder模式应该是:

产品职责变少:

class Car
{
string _name;
public:
    virtual ~Car(){}
    virtual void sayName(){ cout << _name << endl; }
    string getName(){ return _name; }
    void setName(string name){ _name = name; }
};
class Ferrari :public Car
{
public:
    void sayName()
    {
        cout << "i m a car,my name is:" << getName() << endl;
    }
};

builder:

class CarBulider
{
protected:
    Car * _car;
    virtual void designPrototype() = 0;
    virtual void wheelInstall(int) = 0;
    virtual void smartInit() = 0;
    virtual void systemTest() = 0;
    virtual Car* getResult(){ return _car; };
    
    friend class Director;
public:
    virtual ~CarBulider(){}
};

concrete builder:

class FerrariBulider :public CarBulider
{

    virtual void designPrototype();
    virtual void wheelInstall(int);
    virtual void smartInit();
    virtual void systemTest();
public:
    FerrariBulider(){  }
};

void FerrariBulider::designPrototype()
{
    
    cout << "设计汽车原型中。。。" << endl;
    //实际实现代码。。。
    CarBulider::_car = new Ferrari();  //这里创建对象,它将由客户去释放
    CarBulider::_car->setName("Ferrari");
    cout << "原型设计完毕,准备进入下一阶段" << endl;
}
void FerrariBulider::wheelInstall(int time)
{
    cout << "初始化第" << time << "个轮子" << endl;
    cout << "组装中" << endl;
    //实现代码,比如轮子类
    cout << "轮子组装完毕,进入下一阶段" << endl;

}
void FerrariBulider::smartInit()
{
    cout << "机动层初始化" << endl;
    cout << "机动层正常,进入下一阶段" << endl;
}
void FerrariBulider::systemTest()
{
    cout << "汽车性能测试" << endl;
    cout << "安全测试" << endl;
    cout << "试跑正常" << endl;
    cout << "构建成功" << endl;
}

Diretor:

class Director
{
    
public:
    Director(){  }
    Car* construct(CarBulider &);
};
Car* Director::construct(CarBulider &b)
{
      //指针内存泄露问题,如果是这样调用construct(new carbulider).
    b.designPrototype();
    for (int i = 0; i < 4; i++)
    {
        b.wheelInstall(i);
    }
    b.smartInit();
    b.systemTest();
    return b.getResult();
}

使用方式:

int main()
{
    FerrariBulider b;
    Director d;
    Car *f = d.construct(b);
    f->sayName();
    return 0;
}

结果:

细节问题好头疼,c++实现方式很多,又要担心内存泄露。所以把builder之间改成引用,由用户觉决定。但是这个时候又设计到const的问题,如果用const那么相应的函数声明也应该改。

原文地址:https://www.cnblogs.com/wuweixin/p/5450759.html