// // // // // // // // //
///2013.1.18
// // // // // // // // //
Builder模式,
有这样一个笑话:
Builder Pattern是Create-type Pattern,对不对?
哈哈(原创笑话,转载请说明出处),这次要讲的就是能从名字一眼就能看出来的创建型模式——Builder。
【核心】通过Director类指导Builder接口的不同实现类来分步创建完整的对象Product(可在创建过程中传入不同的参数)。
首先来看一下UML图:
如上所示,
上图中最为明显的就是Builder接口(C++为虚基类)中,
不同的创建过程BuildPartA(),BuildPartB(),BuildPartC()了。
具体的实现方法是将一个实现了Builder接口的对象传入Director中(利用构造器或是别的方法),
在Director类中调用Construct方法,
根据传入的Builder的对象,
进行相应的Produce对象的构建过程(例如依次调用上面的BuildPartA.、B、C.)。
这个模式稍微有点复杂,
因为与之前的几个模式不同,
它涉及到了四个类的使用:
指导生产的Director,
生产产品的接口(标准)Builder,
实现Builder接口的ConcreteBuilder,
被ConcreteBuilder创建并存放在Director中(或被返回)的Product。
这个模式有一个显著的问题,
就是初学者很容易将它与AbstractFactory搞混。
正如我们所知道的,
AbstractFactory也是根据统一的产品规格(接口)
生产出来不同的产品。
如果不加细分,
它们两个确实是极为相像的。
但是我们要抓住它们各自的特点:
AbstractFactory就像是生产同一产品,不同品牌的工厂的抽象。就像是小米与苹果的区别。
Builder就像是同一品牌同一产品,但生产过程中因参数不同,最终生产出来的质量不同的抽象。就像是发热的小米与不发热的小米的区别。
Builder更为强调的步骤,步骤,步骤。
这一点请大家一定搞清楚,
不然开头处的笑话答案就会是False了,哈哈。
具体代码实例:
【大致思路】
有这样一个产品:由三个步骤完成,在每个步骤投入的时间不同,最终产品的质量将会分为三种:Bad,Normal,High(请参考Product.cpp).
在Director内部聚合Builder接口,并且将实现了Builder的具体实例类ConcreteBuilder传入Director的构造器中。再由Director的Construct方法指导Product的生成。
【注意事项】
1.最后生成的Product并没有被返回(被雪藏在Director内),其实可以将Construct的返回值类型更改为Product* 来返回具体的Product对象。
2.注意由于这里将传入Builder的过程放在了Director构造器中进行,因此一个Director的对象只对应一个具体的Builder。当然可以将此过程放在Director的另一个方法中进行,这样Director就可以根据传入不同的Builder类型,构建不同的品牌,但这样实现的话,Director也是AbstractFactory!!!
Product.h
#ifndef _PRODUCT_H_ #define _PRODUCT_H_ enum WorkTime { tenHours = 10, twentyHours= 20, thirtyHours = 30 }; class Product { public: Product(int equality); private: ~Product(){} }; #endif
#include "Product.h" #include<iostream> Product::Product(int equality) { std::cout<<"Equality: "<<equality; if(equality <= 50) std::cout<<" --Bad"<<std::endl; else if(equality <= 70) std::cout<<" --Normal"<<std::endl; else std::cout<<" --High"<<std::endl; }
#ifndef _BUILDER_H_ #define _BUILDER_H_ #include"Product.h" class Builder { public: Builder(){} ~Builder(){} virtual void buildFirstPart(WorkTime e) = 0; virtual void buildSecondPart(WorkTime e) = 0; virtual void buildThridPart(WorkTime e) = 0; virtual Product* getProduct() = 0; private: int totalEquality; }; class ConcreteBuilder: public Builder { public: ConcreteBuilder(){totalEquality = 0;} void buildFirstPart(WorkTime e); void buildSecondPart(WorkTime e); void buildThridPart(WorkTime e); Product* getProduct(); private: int totalEquality; }; #endif
#include"Builder.h" void ConcreteBuilder::buildFirstPart(WorkTime e) { //Initial equality before build product. totalEquality = 0; this->totalEquality += e; } void ConcreteBuilder::buildSecondPart(WorkTime e) { this->totalEquality += e; } void ConcreteBuilder::buildThridPart(WorkTime e) { this->totalEquality += e; } Product* ConcreteBuilder::getProduct() { return new Product(totalEquality); }
Director.h
#ifndef _DIRECTOR_H_ #define _DIRECTOR_H_ #include"Builder.h" class Director { public: Director(Builder* bdr); void Construct(WorkTime worktime_1,WorkTime worktime_2,WorkTime worktime_3); private: Builder* builder; }; #endif
#include"Director.h" Director::Director(Builder* bdr) { this->builder = bdr; } void Director::Construct(WorkTime worktime_1,WorkTime worktime_2,WorkTime worktime_3) { builder->buildFirstPart(worktime_1); builder->buildSecondPart(worktime_2); builder->buildThridPart(worktime_3); builder->getProduct(); }
#include"Director.h" int main() { Director* director = new Director(new ConcreteBuilder()); //putted 40 hours in total. director->Construct(tenHours,tenHours,twentyHours); //putted 80 hours in total. director->Construct(twentyHours,thirtyHours,thirtyHours); return 0; }
最后要勉励大家一下:
人生就是一个大的Director,
我们每个人的行为就是传入方法中的实参,
经过相同的人生阶段,
在人生的最后一刻我们就会return 自己的结果,
最后是Bad equality,
Normal,还是 Excellent.
都将取决于我们自身。
值此契机,
与君共勉。