意图
对象的构建与表示分离,用同样的创建过程可以创建不同的对象
适应性
创建的算法与对象的组成独立
同样的构造过程允许构造不同的对象
Builder Patten
组成
- 抽象建造者Builder
- 具体建造者ConcreteBuilder
- 指挥者Director
- 产品角色Product
UML图
流程图
Director要对product进行处理,但可能有多种product, 所以我们需要一种builder来专门创建我们所需的product, 再有director进行处理, 因此Director可以不关心builder是怎么具体的创建过程. 这就完成了Director的处理算法与product的创建过程的分离.
- 达到了对Director的复用;
- 对product的创建过程的封装;
适用性
- 当对象的构建过程与构建的组成内容以及这些内容的具体装配方式独立时;
- 构造过程得到的对象允许有不同的表示,即可能对象之间没什么太多的区别;
实现
- Builder类可以构造所有的product,因此它的接口必须很普遍, ConcreteBulider只选择它感兴趣的接口来实现自己的product;
- Builder类不需要虚接口, 因为product之间可能没有太多的关系,无法从众多的product之间提取出公共接口, 这里的dirctor只关注哪个具体的对象在适用;
- Builder类中的接口以空函数的形式存在,不是纯虚函数;
总结
- Director在作用就是完成对产品A与B的创建过程的封装,如流程图中,产品A与B的具体创建过程一样,都有步骤一与步骤二,因此,通过Director的封装,用户就不会知道产品A与B的具体创建步骤
- 该模式完成“产品的使用”—-“产品的组装过程”—-“产品的部件”进行分离, 如产品提供如下部件:
class BuildProA // 提供不同的产品部件 { public: void buildPartA(){pro.partA = ... }; void buildPartB(){Pro.partB = ... }; /* ...*/ private: Product* pro; // 具体创建的产品存放于这里 }; class Builder { public: virtual void buildPartA(){}; virtual void builderPartB(){}; virtual void builderPartC(){}; virtual Product* GetProduct(){}; // 只提供接口 }; class Director { public: product* CreateProduct(Builder& buldr) // 指挥具体的产品创建流程(因此可以用同样的部件创建不同形式的产品,也可以用其他产品类的部件创建完全不同的产品) { buldr.bulidPartA(); buldr.bulidPartB(); return buldr.GetProduct(); } private: product* UsedProduct; };
// 使用
Product* pro;
BuildProA buldA;
Director direct;
direct.CreateProduct(buldA);
pro = buldA.GetProduct();
总结
- 同样的过程可以又不同的结果, 如造一辆汽车会有稳定的流程, 但汽车的具体形状则是千变万化;
- 所以, 可以在Director中规定建造的具体流程, 二流程中调用的都是接口函数,函数的具体实现则是由ConcreteBuilder实现,这样就可以用同样的流程造出不同的产品;