设计模式之Build(生成者模式)
一、生成器模式的定义:
生成器模式也称为建造者模式。生成器模式的意图在于将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示(GoF)。在软件设计中,有时候面临着一个非常复杂的对象的创建工作。这个复杂的对象通常可以分成几个较小的部分,由各个子对象组合出这个复杂对象的过程相对来说比较稳定,但是子对象的创建过程各不相同并且可能面临变化。根据OOD中的OCP原则,应该对这些子对象的创建过程进行变化封装。
二、生成模式的类结构图:
builer模式中主要有两个角色,一个是builder(相当于底层的建筑工人),一个是director(相当于设计师)。builder负责提供构建对象各个部分的功能以及最后组装对象的功能,而director负责调用builder的功能来创建对象。
Builder:为创建Product对象的各个部件指定抽象接口。
ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
Director:构造一个使用Builer接口的对象。
Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,以及将这些部件装配成最终产品的接口。
三、代码示例
假设要组装一辆自行车,并且自行车就是车轮和车架组成。
Builder对应于组装自行车所使用的车轮和车架
ConcreteBuiler对应于自行车的车轮和车架,同时可以返回一辆自行车。
Product对应于自行车。
Director表示组装过程。
此时我们再来理解下面这句话:“在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。”
自行车就是“一个复杂对象”,它有车轮和车架组成,但不管车轮和车架这两个部件怎么变化,生产一辆自行车的过程是不会变的,即组装过程是不会变的。
下面是Java示例代码:
- /**
- * A bike as a concrete product we got finally
- *
- */
- public class Bike {
- //自行车车架数量
- int frameNumber;
- //自行车轮子数量
- int wheelNumber;
- public Bike(){
- frameNumber = 1;
- wheelNumber = 4;
- }
- public int getFrameNumber() {
- return frameNumber;
- }
- public int getWheelNumber() {
- return wheelNumber;
- }
- }
- /**
- *
- * An abstract Builder
- */
- public abstract class BikeBuilder {
- //构建bike的框架
- public abstract void BuildFrame(int frameNumber);
- //构建bike的轮子
- public abstract void BuildWheels(int wheelNumber);
- //获取构建好的完整的产品
- public abstract Bike getBike();
- }
- /**
- *
- *构建自行车的各个部件
- */
- public class ConcreteBikeBuilder extends BikeBuilder {
- Bike bike;
- public ConcreteBikeBuilder(){
- bike = new Bike();
- }
- @Override
- public void BuildFrame(int frameNumber) {
- bike.frameNumber = frameNumber;
- }
- @Override
- public void BuildWheels(int wheelNumber) {
- bike.wheelNumber = wheelNumber;
- }
- @Override
- public Bike getBike() {
- return bike;
- }
- }
- /**
- *
- *组装自行车
- */
- public class BikeDirector {
- public void createBike(BikeBuilder concreteBuilder){
- concreteBuilder.BuildFrame(1);
- concreteBuilder.BuildWheels(4);
- }
- }
- public class TestClient {
- public static void main(String[] args) {
- Bike bike = new Bike();
- BikeBuilder builder = new ConcreteBikeBuilder();
- BikeDirector director = new BikeDirector();
- director.createBike(builder);
- bike = builder.getBike();
- System.out.println("车架frame:" + bike.getFrameNumber()+"个");
- System.out.println("轮子wheel:" + bike.getWheelNumber()+"个");
- }
- }
测试结果:
- 车架frame:1个
- 轮子wheel:4个
四、优点和缺点
优点如下:
1、将一个复杂对象的创建过程封装起来。
2、解耦了组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。--上面对自行车的分析可以很清楚的看出这点。
3、向客户隐藏产品内部的表现。
4、产品的实现可以被替换,因为客户只看到一个抽象的接口。
缺点如下:
1、经常被用来创建组合结构。
五、适用性
1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
六、实现要点
1、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
2、产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。
4、前面我们说过的抽象工厂模式(AbtractFactory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。