首页 > 代码库 > 创建型-生成器模式(Builder)

创建型-生成器模式(Builder)

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

2、场景描述
编辑软件的“另存为”功能便是生成器模式的一个体现。例如,Word的另存为功能,可以选择将文件存储为doc、docx、pdf、txt等格式,但是通过word的另存为功能转变文档的存储格式时都采用了“文件 --> 另存为”,相同的创建过程。当需要对word支持新的类型转换时,例如,添加*.newtype类型的转换,此时只需在“另存为”对话框的“选择存储类型”中添加一行"*.newtype"即可,用户无需知晓具体的存储格式的转变过程,用户只需获得“newtype”类型的文档产品即可。

3、生成器模式类图

 

 角色

  • Builder:为创建一个Product对象的各个部件指定抽象接口;
  • ConcreteBuilder:实现Builder接口以构造和装配该产品的各个部件;定义并明确它所创建的表示;提供一个检索对象的接口(如GetResult方法);
  • Director:构造一个使用Builder接口的对象;
  • Product:表示被构造的复杂对象(ConcreteBuilder创建该产品的内部表示并定义它的装配过程);包含了定义组成部件的类,包括将这些部件装配成最终产品的接口。

4、协作

  • 用户类创建Director对象,并用它想用的Builder对象进行配置;
  • 导向器Director对象控制想要生成的产品部件,并将部件生成指令传递给Builder;
  • Builder生产组成产品的部件,并将部件组装到产品中;
  • 用户类从生成器类中获取产品。

5、适用性

  • 当创建负责对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构造过程必须允许被构造的对象有不同的表示时。

6、代码实现

  6.1 产品类FormattedFile;

 1 package com.crazysnail.builder; 2  3 /** 4  * 格式化文件,doc、docx、txt、pdf等类型文件的超类  5  */ 6 public class FormattedFile { 7     private String title; 8     private String font; 9     private String paragraph;     //文件基本信息10     11     /*getter、setter方法*/12 }

6.2 Builder类及其子类;
FileFormatConverter类;

 1 /** 2  *  3  *文件格式转换父类,提供了对接口的默认实现 4  * 5  */ 6 public class FileFormatConverter { 7     private FormattedFile file; 8     public FileFormatConverter(){ 9         file = new FormattedFile();10     }    11     /*对Word文字进行转换*/12     public void convertCharacter(){13     }14     15     /*对Word字体进行格式转换*/16     public void convertFont(){17     }18     19     /*对Word段落、标题等进行格式转换*/20     public void convertParagraph(){21     }22     23     public FormattedFile getFile(){24         return file;25     }26 }

所有Builder的父类FileFormatConverter类,当需要对某些方法提供默认实现时,定义为类,此时它的子类中可以对省略对某些父类中方法的重载;当Builder的父类定义为接口时,则每个具体的Builder必须提供对每个接口方法的个性化的定义;可根据实际情况在两种实现上选择。

PdfFormatConverter类; 

 1 public class PdfFormatConverter extends FileFormatConverter { 2     private FormattedFile file; 3  4     public PdfFormatConverter(){ 5         file = new FormattedFile(); 6     } 7     @Override 8     public void convertCharacter(){ 9         System.out.println("将file中的字符转化为pdf中对应的表示");10     }11     12     @Override13     public void convertFont(){14         System.out.println("将file中的字体转化为pdf中的默认字体");15     }16     17     @Override18     public void convertParagraph(){19         System.out.println("将file的段落格式转化为pdf中的段落格式");20     }21     22     public FormattedFile getFile(){23         return file;24     }25 }

PdfFormatConverter作为ConcreteBuilder类,提供了将文件转化为pdf格式文件的实现。

TxtFormatConverter类; 

 1 public class TxtFormatConverter extends FileFormatConverter { 2     private FormattedFile file; 3     public TxtFormatConverter(){ 4         file = new FormattedFile(); 5     }     6     @Override 7     public void convertCharacter(){ 8         System.out.println("将file中的字符转化为txt中的表示"); 9     }10     11     @Override12     public void convertFont(){13         System.out.println("将file中的字符转化为txt中的表示");14     }15     16     /*对于convertParagraph方法使用父类中的默认实现,即不对段落格式进行转换*/17     18     public FormattedFile getFile(){  //定义该方法时,可以将返回类型定义为FormattedFile的子类型TxtFile19         return file;20     }21 }

TxtFormatConverter类作为ConcreteBuilder,提供了将文件转化为txt格式文件的实现,其中convertParagraph方法直接使用了父类中的默认定义。

6.3 Director类;

 1 public class UseFormatConverter { 2     public FormattedFile convertFile(FileFormatConverter converter){ 3         //产品的构件过程是由Director类来调用的 4         converter.convertCharacter(); 5         converter.convertFont(); 6         converter.convertParagraph(); 7          8         FormattedFile file = converter.getFile(); 9                 return file;10     }11 }

Director类调用Builder中的相关接口来构建产品,并且获取产品。

6.4类关系说明;
作为Builder的FileFormatConverter类,提供了对外使用ConcreteBuilder的接口,用户类通过这些接口对产品进行处理,并且Builder提供给用户类获取产品的方法getFile。

7、总结;
 7.1生成器模式的特点;
  • 它使你可以改变一个产品的内部表示——Director类调用Builder类提供的抽象接口来构造产品,Builder类隐藏了整个产品的表示和内部结构;当你需要添加产品的一种新的内部结构和表示时,只需定义一个新的ConcreteBuilder类即可。例如场景描述中需要添加对”newType“类型的支持时,只需添加一个FileFormatConverter的子类NewTypeFormatConverter。
  • 它将构造代码和表示代码分开——整个产品的构造过程是通过Director来控制的,但是产品如何构造是完全在Builder的子类中进行实现的,二者是分离开来的。Builder的具体实现可在不同的Director中共享。
  • 它使你对构造过程进行更精细的控制——产品的构造过程是在Director中一步一步构造的,并不是一下生成的。当构建完成时,Director类从Builder类中获取产品。