定义 Separate the construction of a complex object from its representation so that the saame construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。) 建筑者模式通常有四个角色Product产品类:通常是实现了模板方法模式,也就是有模板方法和基本方法 Builder抽象建造者:规范产品的组建,一般是由子类实现 ConcreteBuilder具体建造者:实现抽象类定义的所有方法,并返回一个组建好的对象。 Director导演类:负责安排已有模块的顺序,然后告诉Builder开始建造。 优点 封装性:使用建造者模式可以使客户端不必知道产品内部的组成细节 建造者独立,容易扩展。 方便用户自由的创建复杂的对象 便于控制细节风险:由于具体的建造者是独立的,因此可以对建造过程逐步细化,并不对其他模块产生任何影响。 使用场景 场景:相同的方法,不同的执行顺序,产生不同的事件结果时,可以使用建造者模式 多个零件或部件,都可以装配到一个对象中,但是产生的运行结果又不相同时,可以使用建造者模式 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时。(注意:这种方法只适用于维护阶段,因为一个对象不容易获得,这应该是在设计阶段考虑的问题,通过建造者模式来柔化创建过程,本来就违反了设计的最初目标) 代码 通用类图
基本的建造者模式 类图
代码 产品类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.pattern.builder.products;import java.util.List;public class Product { private String productName; private List<String> productParts; public void addProductPart (String part) { this .productParts.add(part); } public Product () {} public Product (String productName,List<String> productParts) { this .productName = productName; this .productParts = productParts; } public String getProductName () { return productName; } public void setProductName (String productName) { this .productName = productName; } public List<String> getProductParts () { return productParts; } public void setProductParts (List<String> productParts) { this .productParts = productParts; } @Override public String toString () { return "Product [productName=" + productName + ", productParts=" + productParts + "]" ; } }
建造者(抽象类 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.pattern.builder.template;import com.pattern.builder.products.Product;public abstract class TemplateBuilder { protected Product product = new Product (); public abstract void addPart (String part) ; public abstract void setName (String name) ; public Product create () { return this .product; } public void clear () { product = new Product (); } }
具体的建造者(继承自建造者 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.pattern.builder.template;import java.util.ArrayList;public class TemplateConcreteBuilder extends TemplateBuilder { @Override public void addPart (String part) { if (super .product.getProductParts() == null ){ super .product.setProductParts(new ArrayList <String>()); } super .product.addProductPart(part); } @Override public void setName (String name) { super .product.setProductName(name); } }
导演类(用于指导建造者创建,可有可无)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.pattern.builder.template;import com.pattern.builder.products.Product;public class TemplateDirector { private TemplateBuilder builder; public TemplateDirector (TemplateBuilder builder) { this .builder = builder; } public Product getProduct1 () { builder.clear(); builder.setName("汽车" ); builder.addPart("发动机" ); builder.addPart("轮胎" ); builder.addPart("引擎" ); return builder.create(); } public Product getProduct2 () { builder.clear(); builder.setName("自行车" ); builder.addPart("车龙头" ); builder.addPart("轮胎" ); builder.addPart("车链" ); return builder.create(); } }
测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.pattern;import com.pattern.builder.extend.SimpleBuilder;import com.pattern.builder.products.Product;import com.pattern.builder.template.TemplateBuilder;import com.pattern.builder.template.TemplateConcreteBuilder;import com.pattern.builder.template.TemplateDirector;import org.junit.Test;public class BuilderTest { @Test public void TemplateBuilderTest () { System.out.println("-----------创建一个建造者对象-------------" ); TemplateBuilder builder = new TemplateConcreteBuilder (); System.out.println("-----------创建一个导演对象-------------" ); TemplateDirector director = new TemplateDirector (builder); System.out.println("-----------创建一个预定的产品:汽车-------------" ); Product car = director.getProduct1(); System.out.println(car.toString()); System.out.println("-----------创建一个预定产品:自行车-------------" ); Product bike = director.getProduct2(); System.out.println(bike.toString()); } }
结果
简化的建造者模式 简化后的建造者模式在开源框架中的使用较多,如httpclient的MultipartEntityBuilder
类图
代码 产品类(同上 ) 简化后的建造者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.pattern.builder.extend;import java.util.ArrayList;import java.util.List;import com.pattern.builder.products.Product;public class SimpleBuilder { private String productName; private List<String> productParts; public static SimpleBuilder create () { return new SimpleBuilder (); } public SimpleBuilder setProductName (String productName) { this .productName = productName; return this ; } public SimpleBuilder addProductPart (String part) { if (this .productParts == null ){ this .productParts = new ArrayList <String>(); } this .productParts.add(part); return this ; } public void clear () { this .productName = null ; this .productParts.clear();; } public Product build () { Product product = new Product (this .productName, this .productParts); return product; } }
测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.pattern;import com.pattern.builder.extend.SimpleBuilder;import com.pattern.builder.products.Product;import com.pattern.builder.template.TemplateBuilder;import com.pattern.builder.template.TemplateConcreteBuilder;import com.pattern.builder.template.TemplateDirector;import org.junit.Test;public class BuilderTest { @Test public void SimpleBuilderTest () { System.out.println("-----------通过静态方法创建一个建造者对象-------------" ); SimpleBuilder builder = SimpleBuilder.create(); System.out.println("-----------创建一个预定的产品:汽车-------------" ); Product car = builder.setProductName("汽车" ).addProductPart("发动机" ).addProductPart("轮胎" ).addProductPart("引擎" ) .build(); System.out.println(car.toString()); System.out.println("-----------要用同一个建筑者对象创建一个新的产品需要先清理前一个场景-------------" ); builder.clear(); System.out.println("-----------创建一个预定产品:自行车-------------" ); Product bike = builder.setProductName("自行车" ).addProductPart("车龙头" ).addProductPart("轮胎" ).addProductPart("车链" ) .build(); System.out.println(bike.toString()); } }
运行结果
注意 如果一个建造者要建造多个不同的对象,请注意调用clear来清理场景。顺带一提:如果ArrayList和HashMap定义为类的成员变量,那在方法中的调用一定要做一个clear动作防止数据混乱。 建造者模式关注的是零件类型和装配顺序,这是它与工厂方法模式最大的不同。虽然同为创建类模式,但是注重点不同。