zoukankan      html  css  js  c++  java
  • 设计模式学习总结:(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那么相应的函数声明也应该改。

  • 相关阅读:
    code#5 P2 棋子
    code#5 P1 报告
    ztz11的noip模拟赛T3:评分系统
    20181101noip模拟赛T1
    20181031noip模拟赛T2
    20181031noip模拟赛T1
    Linux进程的五个段
    进程和线程有什么区别
    shell中if条件字符串、数字比对,[[ ]]和[ ]区别
    Python实现单例模式
  • 原文地址:https://www.cnblogs.com/wuweixin/p/5450759.html
Copyright © 2011-2022 走看看