设计模式学习--------9.生成器模式学习

场景:

     考虑导出数据的应用框架,通常在导出的数据形式上有一定的约定方式,对于不同的输出格式,处理步骤都是一样的,但

每步的具体实现是不一样的,像导出成TXT和EXCEL的文本形式不一样,但是导出的数据都会分为文件头,文件体和文件

尾.所以应该将处理步骤导出文件头,导出文件体,导出文件尾这几个固定步骤提炼出来,形成公共的处理过程.今后可能会

有很多种不同输出格式的要求,这就需要在处理过程不变的情况下,能方便地切换不同的输出格式处理。


定义:

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


角色:

 Builder:

生成器接口,定义创建一个Product对象所需的各个部件的操作。

 

package com.kris.study;

public interface Builder {
	public void builderHead();
	public void buidlerFoot();
    public void buildPart();
}


ConcreteBuilder:

 

具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后

的产品对象的方法.

 

package com.kris.study;

public class ConcreteBuilder implements Builder {

	/**
	 *   生成器最终构建的产品对象
	 */
	private Product resultProduct;
	
	public Product getResult(){
		return resultProduct;
	}
	
	@Override
	public void buildPart() {
       //构建某个部件的功能处理
		System.out.println("创建身体");
	}

	@Override
	public void builderHead() {
		System.out.println("创建头部");
	}

	@Override
	public void buidlerFoot() {
		System.out.println("创建腿部");
	}

}

 

package com.kris.study;

public class ConcreteBuilder2 implements Builder {

	/**
	 *   生成器最终构建的产品对象
	 */
	private Product resultProduct;
	
	public Product getResult(){
		return resultProduct;
	}
	
	@Override
	public void builderHead() {
       System.out.println("创建触角");
	}

	@Override
	public void buidlerFoot() {
		 System.out.println("创建躯干");
	}

	@Override
	public void buildPart() {
		System.out.println("创建脚");
	}

}


Director:

 

指导者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象

 

package com.kris.study;

public class Director {
	//持有当前需要使用的生成器对象
     private Builder builder;
     
     public Director(Builder builder){
    	 this.builder = builder;
     }
     
     /**
      * 指导生成器构建最终的产品对象
      */
    public void construct(){
    	 builder.builderHead();
    	 builder.buildPart();
         builder.buidlerFoot(); }}


Product:

产品,表示生成构建的复杂对象,包含多个部件。

package com.kris.study;

public interface Product {
    //定义产品的操作
	public String foot();
	public String head();
	public String body();
}

Client:

客户端

package com.kris.study;

public class Client {
    public static void main(String[] args) {
		Builder builder = new ConcreteBuilder();
		Director direc = new Director(builder);
		direc.construct();
		Builder builder2 = new ConcreteBuilder2();
		Director direc2 = new Director(builder2);
		direc2.construct();
	}
}

 


原理分析:

 

生成器模式的主要功能是构建复杂的产品,而且是细化的,分多个固定步骤构建的产品,这个构建的过程是统一的,不变的.

将变化的部分放到生成器部分,只有配置不同的生成器,那么同样的构建过程,就能构建出不同的产品来。

生成器两个很重要的部分:

1.Builder接口,这里定义了如何构建各个部件,也就是知道每个部件的功能如何实现,以及如何装配这些产品

2.Director指导者,Director负责整体的构建算法,知道如何组合来构建完整的产品.

在Director实现整体构建算法时,遇到需要创建和组合具体部件时,就会委托给Builder完成。

在实际应用中需要指导者Director和生成器Builder之间进行交互来构建产品,方式通过生成器方法的参数和返回值,来

回地传递数据。


采用Builder直接构建复杂的对象,通常会对Builder模式进行一定的简化.

1.由于是用Builder模式来创建某个对象,因此没必要再定义一个Builder接口,提供一个具体构建器类就可以了。

2.将指导者和Client功能合并起来,由Client去指导构建器去构造复杂对象

3.将构建器和被构建对象合并,将类内联化。


考虑一个实际应用,要创建一个合同对象,里面有很多属性值都有约束,要求创建出来的对象满足这些约束规则.约束规

则比如,保险合同通常情况下可以和个人签订,也可以和某个公司签订,但是一份合同不能同时与个人和公司签订。

 

package com.kris.study;

public class InsuranceContract {
   private String contractId;
   
   private String personName;
   
   private String companyName;
   
   private long beginDate;
   
   private long endDate;
   
   private String otherData;
   
   private InsuranceContract(ConcreteBuilder builder){
	   contractId = builder.contractId;
	   personName = builder.personName;
	   companyName = builder.companyName;
	   beginDate = builder.beginDate;
	   endDate = builder.endDate;
	   otherData = builder.otherData;
   }
   
   public static class ConcreteBuilder{
	   
	   private String contractId;
	   
	   private String personName;
	   
	   private String companyName;
	   
	   private long beginDate;
	   
	   private long endDate;
	   
	   private String otherData;

	public ConcreteBuilder(String contractId, long beginDate, long endDate) {
		super();
		this.contractId = contractId;
		this.beginDate = beginDate;
		this.endDate = endDate;
	}


	public ConcreteBuilder setPersonName(String personName) {
		this.personName = personName;
		return this;
	}

	public ConcreteBuilder setCompanyName(String companyName) {
		this.companyName = companyName;
		return this;
	}

	public ConcreteBuilder setOtherData(String otherData) {
		this.otherData = otherData;
		return this;
	}

	public InsuranceContract build(){
		if(contractId == null || contractId.trim().length() == 0){
			throw new IllegalArgumentException("合同编号不能为空");
		}
		
		boolean signPerson = personName != null && personName.trim().length()>0;
		boolean signCompany = companyName != null && companyName.trim().length()>0;
		
		if(signCompany && signPerson){
			throw new IllegalArgumentException("一份合同不能同时与人和公司签订");
		}
		
		if(signCompany == false && signPerson == false){
			throw new IllegalArgumentException("一份合同不能没有签订对象");
		}
		
		if(beginDate<=0){
			throw new IllegalArgumentException("合同必须有保险开始生效的日期");
		}
		
		if(endDate <=0){
			throw new IllegalArgumentException("合同必须有保险失效生效的日期");
		}
		
		if(endDate<=beginDate){
			throw new IllegalArgumentException("保险失效的日期必须大于保险生效日期");
		}
		
		return new InsuranceContract(this);
	}
	   
   }
   
   public void someOperation(){
	   System.out.println("Now in Insurance Contract someOperation =="+this.contractId);
   }
}

 

package com.kris.study;

public class Client {

	
	public static void main(String[] args) {
       InsuranceContract.ConcreteBuilder builder =
    		   new InsuranceContract.ConcreteBuilder("101", 102L, 67890L);
       InsuranceContract contract = builder.setPersonName("张三").
    		   setOtherData("test").build();
       contract.someOperation();
	}

}

优点:
松散耦合,更好的复用性,将构建算法和具体产品实现分离,这样使得构建产品的算法可以复用。
本质: 分离整体构建算法和部件构造


 

posted @ 2014-05-01 23:49  Leo的银弹  阅读(174)  评论(0编辑  收藏  举报