1、简介
一个产品通常有不同的组成部分作为产品的零件,这些零件可能是对象也有可能不是,所以我们通常叫他产品的内部表象,不同的产品有不同的内部表象,使用建造模式可以使客户端不需要知道产品内部有哪些零件,这些零件有什么样的内部关系,他们是如何组成产品的。将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
2、使用场景及能解决的问题
从代码的角度来说,如果你希望分离复杂类型构建规则和类型内部组成,或者希望把相同的构建过程用于构建不同类型的时候可以考虑使用建造者模式。
从应用的角度来说,如果你希望解耦产品的创建过程和产品的具体配件,或者你希望为所有产品的创建复用一套稳定并且复杂的逻辑的时候可以考虑使用建造者模式。
3、类图
对象的构建过程由指导者(Director)完成,具体的组成由具体建造者(Builder)完成,表示与构建分离。
建造者和指导者是建造者模式的关键点,如果进行合并或省略就可能会转变到模版方法模式。
如果对象的建造步骤是简单的,并且产品拥有一致的接口可以转而使用工厂模式。
4、实例
产品相关的类:
package builder;
public interface Product {
void list();
void add(String key, String value);
}
package builder;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;
public class ConcreteProduct implements Product {
Map map = new HashMap();
public void add(String key,String value){
map.put(key,value);
}
public void list(){
System.out.println("I am a Product,I have some parts:");
Iterator it = map.entrySet().iterator();
while(it.hasNext()) {
Map.Entry entry =(Map.Entry)it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key+ ":"+value);
}
}
}
建造者相关的类:
package builder;
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product result();
}
package builder;
public class ConcreteBuilder implements Builder {
public void buildPartA(){
System.out.println("build PartA now");
lnkProduct.add("A","PartA");
}
public void buildPartB(){
System.out.println("build PartB now");
lnkProduct.add("B","PartB");
}
public void buildPartC(){
System.out.println("build PartC now");
lnkProduct.add("C","PartC");
}
public Product result(){
System.out.println("build Success");
return lnkProduct;
}
/**
* @directed*/
private Product lnkProduct = new ConcreteProduct();;
}
指导者相关的类:
package builder;
public abstract class Director {
/**
* @link aggregation
* @directed
*/
protected Builder lnkBuilder;
public Director(Builder builder){
this.lnkBuilder=builder;
}
public abstract void construct();
}
package builder;
public class ConcreteDirector extends Director {
public ConcreteDirector(Builder builder){
super(builder);
}
public void construct(){
lnkBuilder.buildPartA();
lnkBuilder.buildPartB();
lnkBuilder.buildPartC();
}
}
最后看看客户端是如何调用的:
package builder;
public class Client {
/**
* @directed*/
private static Builder builder= new ConcreteBuilder();
/**
* @directed
*/
private static ConcreteDirector director = new ConcreteDirector(builder);
public static void main(String[] args){
director.construct();
Product product = builder.result();
product.list();
}
}
5、优缺点
Builder模式的一个最重要的好处除了将对象构建的“部件”和“过程”解耦之外,还能够保证我们构建出来的对象都是完整的,可用的,具有商业意义的。如果因为构建参数的缺少或错误而导致直接实例化一个对象后才发现对象是不可用的,会浪费系统的资源,使用Builder模式则可用避免这种情况。