声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
/**
* 生成器模式的意图在于将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示(GoF)
* 个人理解:
* 构建一个复杂的对象,对于创建者(Builder)来说,一是要有数据来源(rawData),二是要返回构建好的对象(product)
* 那么AbstractBuilder就自然持有了rawData和product对象
* 然后将创建过程分成相对不变的几个步骤,这几个步骤交由子类去实现,那就实现了不同的Builder能“创建不同的表示”
* 另外,定义一个Director,将Builder创建产品的几个步骤封装到一个方法里,向外提供统一的接口而不暴露细节
*
* 书上考虑了一个数据导出到文件的问题。假设要生成的HTML和XML文件都只包含header和body
*/
abstract class AbstractBuilder {
//构造产品的原始数据。也可以写成方法参数传递:buildHeader(String rawData);buildBody(String rawData);
protected String rawData;
protected FileProduct product;
public abstract void buildHeader();
public abstract void buildBody();
public FileProduct getProduct() {
return product;
}
}
class HTMLBuilder extends AbstractBuilder {
public HTMLBuilder(String rawData) {
this.rawData = rawData;
this.product = new FileProduct();
}
@Override
public void buildHeader() {
String[] rawDatas = rawData.split(",");
product.setHeader("<html:header>" + rawDatas[0] + "</html:header>");
}
@Override
public void buildBody() {
String[] rawDatas = rawData.split(",");
product.setBody("<html:body>" + rawDatas[1] + "</html:body>");
}
}
class XMLBuilder extends AbstractBuilder {
public XMLBuilder(String rawData) {
this.rawData = rawData;
this.product = new FileProduct();
}
@Override
public void buildHeader() {
String[] rawDatas = rawData.split(",");
product.setHeader("<xml:header>" + rawDatas[0] + "</xml:header>");
}
@Override
public void buildBody() {
String[] rawDatas = rawData.split(",");
product.setBody("<xml:body>" + rawDatas[1] + "</xml:body>");
}
}
class FileProduct {
private String header;
private String body;
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String toString() {
return header + "\n" + body;
}
}
class Director {
private AbstractBuilder builder;
public Director(AbstractBuilder builder) {
this.builder = builder;
}
public void build() {
builder.buildHeader();
builder.buildBody();
}
}
public class BuilderPattern {
public static void main(String[] args) {
String rawData = "xx,yy";
AbstractBuilder xmlBuilder = new XMLBuilder(rawData);
Director director = new Director(xmlBuilder);
director.build();
System.out.println(xmlBuilder.getProduct());
AbstractBuilder htmlBuilder = new HTMLBuilder(rawData);
Director director2 = new Director(htmlBuilder);
director2.build();
System.out.println(htmlBuilder.getProduct());
//测试:用Builder模式创建对象
MassiveObject data = new MassiveObject.Builder("001").name("Tom").position("CEO").build();
System.out.println(data);
}
}
/**
* 创建有约束的复杂对象。可以在两个地方加上约束:
* 1、在InsuranceContract的构造函数时加约束
* 2、在Builder的setter里面加约束
*/
class InsuranceContract {
private String id;
private String name;
private String position;
/*
* 访问类别是default,不支持包外的其他类直接利用构造函数来创建InsuranceContract,
* 但也带来一个问题是,同包的其他类可能会直接调用构造函数来创建InsuranceContract
* 因此,较好的办法是像Effective Java里面建议的那样,把Builder做成inner class
*/
//1.可以这里加约束
InsuranceContract(ConcreteBuilder builder) {
this.id = builder.getId();
this.name = builder.getName();
this.position = builder.getPosition();
}
public String toString() {
return "id = " + id + ",name = " + name + ",position = " + position;
}
public void otherOperation() {
}
}
class ConcreteBuilder {
private String id;
private String name;
private String position;
public InsuranceContract build() {
return new InsuranceContract(this);
}
//假设id是必填数据,其他为选填数据
public ConcreteBuilder(String id) {
this.id = id;
}
//将ConcreteBuilder返回
public ConcreteBuilder setName(String name) {
//2.可以这里加约束
this.name = name;
return this;
}
public ConcreteBuilder setPosition(String position) {
this.position = position;
return this;
}
public String getPosition() {
return position;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
/**
* Effective Java里面建议:
* 在生成一个复杂对象(field很多,造成构造函数的参数列表很长且顺序易出错)时,考虑用Builder模式
*/
class MassiveObject {
private String id;
private String name;
private String position;
private MassiveObject(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.position = builder.position;
}
public String toString() {
return "id=" + id + ",name=" + name + ",position=" + position;
}
public static class Builder {
private String id;
private String name;
private String position;
public Builder(String id) {
this.id = id;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder position(String position) {
this.position = position;
return this;
}
public MassiveObject build() {
return new MassiveObject(this);
}
}
}