1. 程式人生 > 實用技巧 >建造者模式

建造者模式

1.1什麼是建造者模式

建立者模式又叫建造者模式,是將一個複雜的物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。建立者模式隱藏了複雜物件的建立過程,它把複雜物件的建立過程加以抽象,通過子類繼承或者過載的方式,動態的建立具有複合屬性的物件。

指揮者(Director)直接和客戶(Client)進行需求溝通,然後指揮者將客戶建立產品的需求劃分為各個部件的建造請求(Builder),將各個部件的建造請求委派到具體的建造者(ConcreteBuilder),各個具體建造者負責進行產品部件的構建,最終構建成具體產品(Product)。
例如以builder模式建立共享單車為例子:

//首先存在一個產品類(三個屬性:支架、座位、輪胎)
public class Bike { 

    private IFrame frame; 
    private ISeat seat; 
    private ITire tire; 
    /*
    getandset方法
    */
} 
// 抽象 builder 類 
public abstract class Builder { 
    //建造支架
    abstract void buildFrame();
    //建造座位
    abstract void buildSeat(); 
    //建造輪胎
    abstract void buildTire(); 
    建造車輛
    abstract Bike createBike(); 
} 
// 具體 builder 類 
public class MobikeBuilder extends Builder{ 
    private Bike mBike = new Bike(); 
    @Override 
    void buildFrame() { 
        mBike.setFrame(new AlloyFrame()); 
    } 
    @Override 
    void buildSeat() { 
        mBike.setSeat(new DermisSeat()); 
    } 
    @Override 
    void buildTire() { 
        mBike.setTire(new SolidTire()); 
    } 
    @Override 
    Bike createBike() { 
        return mBike; 
    } 
} 

public class OfoBuilder extends Builder{ 
    private Bike mBike = new Bike(); 
    @Override 
    void buildFrame() { 
        mBike.setFrame(new CarbonFrame()); 
    } 
    @Override 
    void buildSeat() { 
        mBike.setSeat(new RubberSeat()); 
    } 
    @Override 
    void buildTire() { 
        mBike.setTire(new InflateTire()); 
    } 
    @Override 
    Bike createBike() { 
        return mBike; 
    } 
} 
//指揮者類傳入具體的建造者類。
public class Director { 
    private Builder mBuilder = null; 
    public Director(Builder builder) { 
        mBuilder = builder; 
    } 
    public Bike construct() { 
        mBuilder.buildFrame(); 
        mBuilder.buildSeat(); 
        mBuilder.buildTire(); 
        return mBuilder.createBike(); 
    } 
}
//客戶端使用
public class Click { 
    public static void main(String[] args) { 
        showBike(new OfoBuilder()); 
        showBike(new MobikeBuilder()); 
    } 
    private void showBike(Builder builder) {
        Director director = new Director(builder); 
        Bike bike = director.construct(); 
        bike.getFrame().frame(); 
        bike.getSeat().seat(); 
        bike.getTire().tire(); 
    } 
} 

1.2java中建造者模式的使用

java中的stringbuffer和StringBuilder、springMVC中UriComponents和UriComponentsBuilder。

1.3一般情境下應用:

假如我們需要構造一個包含10個屬性,假如這十個屬性都是可有可無的,那我們可能需要寫很多個重複的set方法程式碼。但是我們可以使用建立一個Builder類,通過Builder類去建立所需要的類。假如我們需要一個Header類,這個Header具有屬性clientid、correlationid等一系列函式。我們大概率會使用下面這種方法去賦值給Header類。

Header header = new Header();
header.setClientId(SOAHeader.SOAP_CLIENT_ID);
header.setCorrelationId(SOAHeader.SOAP_CORRELATION_ID);
。。。。。。

但是如果屬性很多的話,就會顯得程式碼重複切不便於閱讀。我們可以採用下面的方法建造一個HeaderBuilder類。

public class HeaderBuilder {
	
    protected BigInteger replyCd;
    protected String clientId;
    protected String recptId;
    protected String transId;
    protected String correlationId;
    protected String userId;
    protected String logTxt;
    protected String replyMsg;
    protected String systemName;
    
	public HeaderBuilder setReplyCd(BigInteger replyCd) {
		this.replyCd = replyCd;
		return this;
	}
	public HeaderBuilder setClientId(String clientId) {
		this.clientId = clientId;
		return this;
	}
	public HeaderBuilder setRecptId(String recptId) {
		this.recptId = recptId;
		return this;
	}
	public HeaderBuilder setTransId(String transId) {
		this.transId = transId;
		return this;
	}
	public HeaderBuilder setCorrelationId(String correlationId) {
		this.correlationId = correlationId;
		return this;
	}
	public HeaderBuilder setUserId(String userId) {
		this.userId = userId;
		return this;
	}
	public HeaderBuilder setLogTxt(String logTxt) {
		this.logTxt = logTxt;
		return this;
	}
	public HeaderBuilder setReplyMsg(String replyMsg) {
		this.replyMsg = replyMsg;
		return this;
	}
	public HeaderBuilder setSystemName(String systemName) {
		this.systemName = systemName;
		return this;
	}
    
	public Header buildHeader(){
		return new Header(replyCd, clientId, recptId, transId, correlationId, userId, logTxt, replyMsg, systemName);
	} 
   
}

那麼在賦值Header類時。我們的程式碼就可以變為:

Header header = new HeaderBuilder()
   .setClientId(SOAHeader.SOAP_CLIENT_ID)
   .setCorrelationId(SOAHeader.SOAP_CORRELATION_ID)
   .buildHeader();

這樣可讀性就大幅增加了。