读《研磨设计模式》-代码笔记-生成器模式-Builder

[b]声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客[url]http://chjavach.iteye.com/[/url][/b]




/**
* 生成器模式的意图在于将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示(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);
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值