建造者模式實踐
阿新 • • 發佈:2018-12-01
建造者模式是一種常見的設計模式,屬於建立型模式,我們常見的工廠、單例、原型、包括《重構與模式》一書中提到的creation method都屬於建立型模式。建造者適合用於構建複雜物件,它可以將建立和表示分離,使我們的程式碼可讀性更好,更易於維護。
在我們的實際開發中,經常會構建一些實體物件,比如,在筆者參與的交易系統中,會記錄使用者的每一筆支付,我們在建立支付實體物件時,通常會寫出這樣的程式碼:
PaymentRecord paymentRecord = new PaymentRecord();
// 設定一些基礎屬性
paymentRecord.setId(sequence.nextValue ());
paymentRecord.setUserId(...);
...
// 計算價格
Long discountFee = ...; // 促銷金額
Long totalFee = calculateTotalFee(..., discountFee); // 計算總金額
paymentRecord.setTotalFee(totalFee);
paymentRecord.setDiscountFee(discountFee);
...
// 一些擴充套件屬性的設定
...
// 不同的業務的一些個性化引數設定
...
我們會發現,這樣一個物件的構建過程非常的複雜,每次需要對這裡做一些改動時,都需要埋頭於這一堆繁瑣的程式碼中苦苦的尋找,可讀性非常差,維護起來相當麻煩,而這樣的程式碼在我們的實際開發過程中是非常常見的,我們可以利用建造者模式來進行一次重構。首先,抽象建造者:
/**
* PaymentRecord 建造者
*/
public interface PaymentRecordBuilder {
/**
* 構建payment record
*/
PaymentRecord build();
}
接下來根據不同的構建需求實現不同的建造者:
/**
* 根據支付請求構建 PaymentRecord
*/
public class RequestPaymentRecordBuilder implements PaymentRecordBuilder {
private PaymentRequest paymentRequest;
public RequestPaymentRecordBuilder(PaymentRequest paymentRequest) {
this.paymentRequest = paymentRequest;
}
@Override
public PaymentRecord build() {
PaymentRecord paymentRecord = new PaymentRecord();
buildBase(paymentRecord);
buildFee(paymentRecord);
buildExtension(paymentRecord);
buildBiz(paymentRecord);
return paymentRecord;
}
/**
* 構建基礎屬性
*/
private void buildBase(PaymentRecord paymentRecord) {
paymentRecord.setId(sequence.nextValue());
paymentRecord.setUserId(paymentRequest.getUserId());
...
}
/**
* 費用
*/
private void buildFee(PaymentRecord paymentRecord) {
// 獲取促銷金額
Long discountFee = ...;
// 計算總金額
Long totalFee = calculateTotalFee(..., discountFee);
paymentRecord.setTotalFee(totalFee);
paymentRecord.setDiscountFee(discountFee);
...
}
/**
* 構建擴充套件屬性
*/
private void buildExtension(PaymentRecord paymentRecord) {
...
}
/**
* 構建不同業務相關
*/
private void buildBiz(PaymentRecord paymentRecord) {
...
}
}
這樣整個實體物件的構建過程就非常清晰,將整個構建過程拆分開來,相互獨立,層次很分明,每一個子構建過程如果還是比較複雜,同樣可以抽象另外的建造者進行構建。這樣看似簡單的重構,卻能大大的提高程式的可讀性和可維護性,然後我們就可以使用這樣的方式來構建實體物件:
PaymentRecord paymentRecord = new RequestPaymentRecordBuilder(paymentRequest).build();