簡體   English   中英

如Effective Java中所述,嵌套的Builder類是否真的有必要?

[英]Is a nested Builder class really necessary as described in Effective Java?

因此,在着名的Effective Java書中,它引入了一個Builder模式 ,您可以在其中使用內部靜態Builder類來實例化一個類。 這本書建議了以下類的設計:

public class Example {
    private int a;
    private int b;

    public static class Builder() {
        private int a;
        private int b;

        public Builder a(int a) {
            this.a = a;
            return this;
        }

        public Builder b(int b) {
            this.b = b;
            return this;
        }

        public Example build() {
            return new Example(this);    
        }
    }

    private Example(Builder builder) {
        this.a = builder.a;
        this.b = builder.b;
    }
}

但是我無法理解為什么我們真的需要一個內部的Builder class 上面的代碼有字段聲明的重復行(int a,b),如果我們有更多字段,這將變得相對混亂。

為什么不擺脫的Builder類,並讓Example類采取對所有set那名的方法Builder類?

因此,要實例化Example ,它將成為Example e = new Example().a(3).b.(3); 代替Example e = new Example.Builder.a(3).b(3).build();


注意:本書為具有很長參數列表的類建議了這種模式。

Builder是構建復雜對象的模式。 我不認為你的榜樣很復雜; 實際上,構建器添加了大量不必要的代碼,而不僅僅是使用構造函數參數。

您想要使用構建器的原因有幾個:

  • 構造復雜的不可變對象。 不可變對象需要具有最終(或邏輯上最終)字段,因此必須在構造時設置它們。

    假設您有N個字段,但您只想在某些用例中明確設置其中的一些字段。 您需要最多2 ^ N個構造函數來覆蓋所有情況 - 稱為“telescoping”,因為參數列表的長度變得越來越長。 構建器允許您為可選參數建模:如果您不想設置該參數,請不要調用該setter方法。

  • 允許自我記錄參數的含義。 通過適當地命名setter方法,您可以一目了然地看到值的含義。

    它還有助於驗證您是否意外地反轉了相同類型的參數,因為您可以看到每個值的用途。

如果外部類中的字段是final,那么如果要逐步指定參數值,則必須使用構建器,因為必須在構造函數中初始化所有字段。

構建器內部類允許以遞增方式初始化字段。

正如其他人所指出的那樣,這也適用於不可變對象。 這些領域不一定是最終的; 如果在外層沒有提供制定者,它們將是有效的。

構建器可以比直接構造更有效地累積參數。 考慮一下StringBuilder 它分配一個臨時緩沖區來累積部分結果。 其案例中的“構建”操作是toString()

最后,可能有一些你在類的構造函數中無法做到的事情。 如果您需要將值傳遞給超級構造函數,但該值不是構造函數的參數的一部分,則可能無法,因為您必須首先調用super() ,並且您可能無法創建argument(s)作為super(...)調用中的一個簡單表達式。 想到BoxLayout。 您將JPanel傳遞給BoxLayout構造函數。 您將布局傳遞給JPanel構造函數。 雞肉和雞蛋。 而這種代碼是不允許的,因為this尚未構成。

class X extends JPanel {
    X() {
        super( new BoxLayout(this) );   // Error: Cannot use "this" yet
    }
}

幸運的是, JPanel不是一成不變的; 你可以在施工后設置布局。

理由是復雜的課程。 請注意, Builder對象返回自身,因此可以進行鏈接,例如:

Example exp = Example.Builder().a(5).b(10).build();

在某些情況下,Apache使用此方法來允許增量設置各種值。 它還允許.build()方法對所有正確的值進行一些檢查,以便在需要時創建對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM