1. 程式人生 > >建造者模式實踐

建造者模式實踐

建造者模式是一種常見的設計模式,屬於建立型模式,我們常見的工廠、單例、原型、包括《重構與模式》一書中提到的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();