Java Academy · Lektion

Builder-mönstret med fluent-API

Konstruera komplexa objekt stegvis med en fluent builder för att undvika telescoping-konstruktorer.

Lektion 4 av 413 steg

Builder-mönstret med fluent-API är en gratis lektion i Java Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Java Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Java Academy innehåller totalt 4 lektioner.

Problemet med teleskoperande konstruktorer

När en klass har många valfria parametrar blir konstruktorerna allt fler: två parametrar, tre parametrar, fyra parametrar och så vidare. Builder-mönstret löser detta med ett fluent-API för stegvis konfigurering.

// Without builder — hard to read:
Pizza p = new Pizza("large", "thin", true, false, true, false, "mozzarella");

Grundläggande Builder-struktur

Skapa en statisk nästlad Builder-klass. Den yttre klassen har en privat konstruktor som tar emot buildern. Varje setter i buildern returnerar this för att möjliggöra fluent-kedjor.

public final class Pizza {
    private final String size, crustType, cheese;
    private final boolean extraSauce, pepperoni;
    private Pizza(Builder b) {
        this.size = b.size; this.crustType = b.crustType;
        this.cheese = b.cheese; this.extraSauce = b.extraSauce;
        this.pepperoni = b.pepperoni;
    }
    public static class Builder {
        private final String size;
        private String crustType = "regular", cheese = "mozzarella";
        private boolean extraSauce, pepperoni;
        public Builder(String size) { this.size = size; }
        public Builder crustType(String c) { this.crustType = c; return this; }
        public Builder cheese(String c)    { this.cheese = c;    return this; }
        public Builder extraSauce()        { this.extraSauce = true; return this; }
        public Builder pepperoni()         { this.pepperoni = true; return this; }
        public Pizza build()               { return new Pizza(this); }
    }
}

Använda ett fluent-API

Buildern kan läsas som en mening. Obligatoriska parametrar anges i konstruktorn, medan valfria parametrar anges genom metodanrop. Det avslutande anropet till build() skapar det oföränderliga objektet.

Pizza p = new Pizza.Builder("large")
    .crustType("thin")
    .extraSauce()
    .pepperoni()
    .build();
System.out.println(p);

Validering i build()

Lägg till valideringslogik i build() innan objektet skapas. Kasta IllegalStateException eller IllegalArgumentException för ogiltiga kombinationer.

public Pizza build() {
    if (size == null || size.isBlank())
        throw new IllegalArgumentException("Size required");
    if (extraSauce && crustType.equals("stuffed"))
        throw new IllegalStateException("No extra sauce on stuffed crust");
    return new Pizza(this);
}

Builder för oföränderliga objekt

Eftersom den yttre klassen skapas från buildern i ett enda steg kan alla fält vara final. Det gör det resulterande objektet helt oföränderligt och trådsäkert.

public final class Address {
    private final String street, city, country;
    private final String postalCode;
    private Address(Builder b) { ... } // all finals
    // no setters — immutable!
}

Generisk Builder med självrefererande typ

För arvshierarkier använder du en rekursiv generisk typparameter (SELF extends Builder<SELF>) så att builders i underklasser returnerar underklassens typ från kedjade metoder.

public abstract static class Builder<SELF extends Builder<SELF>> {
    String name;
    @SuppressWarnings("unchecked")
    public SELF name(String n) { this.name = n; return (SELF) this; }
    public abstract Vehicle build();
}

Lombok @Builder

Lomboks @Builder genererar hela builder-infrastrukturen vid kompilering. Använd @Builder.Default för standardvärden för fält och @Singular för samlingar.

@Builder
public class Report {
    private final String title;
    @Builder.Default private final int pageCount = 1;
    @Singular private final List<String> authors;
}
// Usage:
Report r = Report.builder().title("Q4").author("Alice").author("Bob").build();

Builder i JDK

Många JDK-klasser använder Builder-liknande API:er: StringBuilder, HttpRequest.newBuilder(), ProcessBuilder och Stream.Builder. Lär dig att känna igen mönstret.

HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Accept", "application/json")
    .GET()
    .build();

Builder jämfört med Factory

Använd Builder när ett objekt kräver många parametrar och stegvis konfigurering. Använd Factory när alla varianter är enkla och skapandet kan göras i ett enda anrop.

Builder för testdata

Builders är särskilt användbara i tester: skapa en grundläggande builder i en hjälpfunktion och skriv sedan över endast de fält som är relevanta för varje testfall. Då förblir testerna DRY och lättlästa.

User defaultUser() { return new User.Builder("test@example.com").name("Test User").build(); }
User adminUser()   { return new User.Builder("admin@example.com").name("Admin").role(ADMIN).build(); }

Trådsäkerhet

Buildern är inte trådsäker i sig — dela inte en Builder mellan trådar. Produkten som byggs kan vara oföränderlig och trådsäker om alla fält är final och inga föränderliga objekt delas.

Snabb kontroll

Vad gör en builder-metod "fluent"?

Sammanfattning

Builder löser problemet med teleskoperande konstruktorer. Använd en statisk nästlad Builder-klass, returnera this från varje setter, validera i build() och skapa ett oföränderligt objekt. Lomboks @Builder automatiserar standardkoden.

Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
104
Lektioner
374

Vanliga frågor

Är lektionen ”Builder-mönstret med fluent-API” gratis?

Ja – hela texten till ”Builder-mönstret med fluent-API” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Java Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Java Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Builder-mönstret med fluent-API”?

Konstruera komplexa objekt stegvis med en fluent builder för att undvika telescoping-konstruktorer. Ni övar på Java Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Java Academy?

Du behöver inga förkunskaper. Utbildningen i Java Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Builder-mönstret med fluent-API”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Java Academy-lektionen?

Ja. Varje Java Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Singleton: trådsäkra implementationer
  2. Fabrikmetodmönstret
  3. Abstrakt fabrik för produktfamiljer
  4. Builder-mönstret med fluent-API
← Tillbaka till Java Academy