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模式則可用避免這種情況。