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

声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客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);
		}
	}
}



你可能感兴趣的:(java,设计模式)