1、簡介
一個產(chǎn)品通常有不同的組成部分作為產(chǎn)品的零件,這些零件可能是對象也有可能不是,所以我們通常叫他產(chǎn)品的內(nèi)部表象,不同的產(chǎn)品有不同的內(nèi)部表象,使用建造模式可以使客戶端不需要知道產(chǎn)品內(nèi)部有哪些零件,這些零件有什么樣的內(nèi)部關(guān)系,他們是如何組成產(chǎn)品的。將產(chǎn)品的內(nèi)部表象和產(chǎn)品的生成過程分割開來,從而使一個建造過程生成具有不同的內(nèi)部表象的產(chǎn)品對象。建造模式使得產(chǎn)品內(nèi)部表象可以獨(dú)立的變化,客戶不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)。建造模式可以強(qiáng)制實(shí)行一種分步驟進(jìn)行的建造過程。
2、使用場景及能解決的問題
從代碼的角度來說,如果你希望分離復(fù)雜類型構(gòu)建規(guī)則和類型內(nèi)部組成,或者希望把相同的構(gòu)建過程用于構(gòu)建不同類型的時(shí)候可以考慮使用建造者模式。
從應(yīng)用的角度來說,如果你希望解耦產(chǎn)品的創(chuàng)建過程和產(chǎn)品的具體配件,或者你希望為所有產(chǎn)品的創(chuàng)建復(fù)用一套穩(wěn)定并且復(fù)雜的邏輯的時(shí)候可以考慮使用建造者模式。
3、類圖
對象的構(gòu)建過程由指導(dǎo)者(Director)完成,具體的組成由具體建造者(Builder)完成,表示與構(gòu)建分離。
建造者和指導(dǎo)者是建造者模式的關(guān)鍵點(diǎn),如果進(jìn)行合并或省略就可能會轉(zhuǎn)變到模版方法模式。
如果對象的建造步驟是簡單的,并且產(chǎn)品擁有一致的接口可以轉(zhuǎn)而使用工廠模式。
4、實(shí)例
產(chǎn)品相關(guān)的類:
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);
}
}
}
建造者相關(guān)的類:
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();;
}
指導(dǎo)者相關(guān)的類:
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();
}
}
最后看看客戶端是如何調(diào)用的:
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、優(yōu)缺點(diǎn)
Builder模式的一個最重要的好處除了將對象構(gòu)建的“部件”和“過程”解耦之外,還能夠保證我們構(gòu)建出來的對象都是完整的,可用的,具有商業(yè)意義的。如果因?yàn)闃?gòu)建參數(shù)的缺少或錯誤而導(dǎo)致直接實(shí)例化一個對象后才發(fā)現(xiàn)對象是不可用的,會浪費(fèi)系統(tǒng)的資源,使用Builder模式則可用避免這種情況。