流殃的博客

| Comments

没有使用模式

package com.zhss.designpattern.builder;

public class WithoutBuilderPatternDemo {
	
	public static void main(String[] args) {
		// 构造这个复杂的product对象
		Product product = new Product();
		// 设置field1属性
		System.out.println("在设置field1之前进行复杂的校验逻辑");  
		product.setField1("值1");  
		// 设置field2属性
		System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");  
		product.setField2("值2");  
		// 设置field3属性
		System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
		product.setField3("值3");  
		
		// 上面是简化的一个逻辑,实际上对于一些有几十个字段,甚至是上百个字段的复杂对象的构建
		// 上面那段代码会极度膨胀,非常复杂
		// 一个是说,大量代码堆积在一起,维护性非常差,可读性非常差,一坨代码,跟屎一样,读不懂,没法改
		// 另外一个,就是说,这段逻辑,如果在多个地方都有使用的话,一旦这段逻辑出现了一些变化,那么可能就需要
		// 在多个地方修改这一大坨跟屎一样的代码
		// 把不同的构造的步骤,抽取成某一个方法
  	}
	
	public static class Product {
		
		private String field1;
		private String field2;
		private String field3;
		
		public String getField1() {
			return field1;
		}
		public void setField1(String field1) {
			this.field1 = field1;
		}
		public String getField2() {
			return field2;
		}
		public void setField2(String field2) {
			this.field2 = field2;
		}
		public String getField3() {
			return field3;
		}
		public void setField3(String field3) {
			this.field3 = field3;
		}
		
	}
	
}

使用模式

package com.zhss.designpattern.builder;

public class BuilderPatternDemo {
	
	public static void main(String[] args) {
		Director director = new Director(new ConcreteBuilder());  
		Product product = director.build("值1", "值2", "值3");  
		System.out.println(product);  
		
		// 好处1:通过builder接口将复杂构建步骤拆分成了多个部分,代码逻辑清晰,维护性和扩展性都很好
		// 好处2:将对象构建的过程,封装在了director里面,director来基于builder进行构建,构建逻辑修改,不需要修改很多地方
		// 好处3:相对于工厂,有一个很好的抽象设计,director和builder
	}
	
	public static class Product {
		
		private String field1;
		private String field2;
		private String field3;
		
		public String getField1() {
			return field1;
		}
		public void setField1(String field1) {
			this.field1 = field1;
		}
		public String getField2() {
			return field2;
		}
		public void setField2(String field2) {
			this.field2 = field2;
		}
		public String getField3() {
			return field3;
		}
		public void setField3(String field3) {
			this.field3 = field3;
		}
		
		@Override
		public String toString() {
			return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
		}
		
	}
	
	public interface Builder {
		
		void field1(String value);
		void field2(String value);
		void field3(String value);
		Product create();
		
	}
	
	public static class ConcreteBuilder implements Builder {

		private Product product = new Product();
		
		public void field1(String value) {
			System.out.println("在设置field1之前进行复杂的校验逻辑");  
			product.setField1(value); 
		}
		
		public void field2(String value) {
			System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");  
			product.setField2(value);
		}

		public void field3(String value) {
			System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
			product.setField3(value);  
		}
		
		public Product create() {
			return product;
		}
		
	}
	
	/**
	 * director是面向builder的接口,来编程的
	 * director可以复杂控制构建的一个步骤,具体的每个步骤的逻辑封装在具体的builder类中
	 * 如果我们此时要更换一整套的构建逻辑,可以再搞一个新的builder类就可以了
	 * 但是我们的整个构建步骤是没有任何改变的
	 * 
	 * 如果整个构建步骤变化了,但是对构建的逻辑是没有影响的
	 * 
	 * @author zhonghuashishan
	 *
	 */
	public static class Director {
		
		private Builder builder;
		
		public Director(Builder builder) {
			this.builder = builder;
		}
		
		public Product build(String field1, String field2, String field3) {
			builder.field1(field1);
			builder.field2(field2);
			builder.field3(field3);  
			return builder.create();
		}
		
	}
	
}

优化后的模式

package com.zhss.designpattern.builder;

public class OptimizedBuilderPatternDemo {
	
	public static void main(String[] args) {
		Product product = new ConcreteBuilder()
				.field1("值1")
				.field2("值2")
				.field3("值3")
				.create();
		System.out.println(product);  
		
		// 现在基本上流行的一些开源框架,构造器模式的运用,一般都是上面这种变种模式
	}
	
	public static class Product {
		
		private String field1;
		private String field2;
		private String field3;
		
		public String getField1() {
			return field1;
		}
		public void setField1(String field1) {
			this.field1 = field1;
		}
		public String getField2() {
			return field2;
		}
		public void setField2(String field2) {
			this.field2 = field2;
		}
		public String getField3() {
			return field3;
		}
		public void setField3(String field3) {
			this.field3 = field3;
		}
		
		@Override
		public String toString() {
			return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
		}
		
	}
	
	public interface Builder {
		
		Builder field1(String value);
		Builder field2(String value);
		Builder field3(String value);
		Product create();
		
	}
	
	public static class ConcreteBuilder implements Builder {

		private Product product = new Product();
		
		public Builder field1(String value) {
			System.out.println("在设置field1之前进行复杂的校验逻辑");  
			product.setField1(value); 
			return this;
		}
		
		public Builder field2(String value) {
			System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");  
			product.setField2(value);
			return this;
		}

		public Builder field3(String value) {
			System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
			product.setField3(value);  
			return this;
		}
		
		public Product create() {
			return product;
		}
		
	}
	
}

总结

好处:

  1. 通过builder接口将复杂构建步骤拆分成了多个部分,代码逻辑清晰,维护性和扩展性都很好
  2. 将对象构建的过程,封装在了director里面,director来基于builder进行构建,构建逻辑修改,不需要修改很多地方
  3. 相对于工厂,有一个很好的抽象设计,director和builder

Comments

评论