Können Sie in Java das Builder-Muster mit erforderlichen und neu zuweisbaren Feldern verwenden?

Dies hängt mit der folgenden Frage zusammen:

Wie kann das Builder-Muster verbessert werden?

Ich bin gespannt, ob es möglich ist, einen Builder mit den folgenden Eigenschaften zu implementieren:

Einige oder alle Parameter sind erforderlichKeine Methode empfängt viele Parameter (d. H. Keine Liste der Standardeinstellungen, die an die anfängliche Builder-Factory-Methode übergeben wurden).Alle Builder-Felder können beliebig oft neu zugewiesen werdenDer Compiler sollte überprüfen, ob alle Parameter gesetzt wurdenEs ist in Ordnung, vorauszusetzen, dass die Parameter anfänglich in einer bestimmten Reihenfolge festgelegt werden. Sobald jedoch ein Parameter festgelegt wurde, kann dieser Parameter für alle folgenden Builder erneut festgelegt werden (d. H. Sie können den Wert eines beliebigen Felds des gewünschten Builders neu zuweisen).Für Setter sollte kein doppelter Code vorhanden sein (z. B. keine überschreibenden Setter-Methoden in Builder-Subtypen)

Ein fehlgeschlagener Versuch ist unten (leere private Konstruktoren weggelassen). Betrachten Sie die folgende Implementierung von Toy Builder, und beachten Sie, dass in der Zeile mit "Foo f2" ein Compilerfehler auftritt, da der geerbte Setter für a ein BuilderB und kein BuilderFinal zurückgibt. Gibt es eine Möglichkeit, das Java-Typensystem zu verwenden, um die Rückgabetypen der Setter zu parametrisieren, um die oben genannten Ziele zu erreichen, oder um sie auf eine andere Weise zu erreichen?

public final class Foo {

    public final int a;
    public final int b;
    public final int c;

    private Foo(
            int a,
            int b,
            int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public static BuilderA newBuilder() {
        return new BuilderC();
    }

    public static class BuilderA {
        private volatile int a;

        public BuilderB a(int v) {
            a = v;
            return (BuilderB) this;
        }

        public int a() {
            return a;
        }
    }

    public static class BuilderB extends BuilderA {
        private volatile int b;

        public BuilderC b(int v) {
            b = v;
            return (BuilderC) this;
        }

        public int b() {
            return b;
        }
    }

    public static class BuilderC extends BuilderB {
        private volatile int c;

        public BuilderFinal c(int v) {
            c = v;
            return (BuilderFinal) this;
        }

        public int c() {
            return c;
        }
    }

    public static class BuilderFinal extends BuilderC {

        public Foo build() {
            return new Foo(
                    a(),
                    b(),
                    c());
        }
    }

    public static void main(String[] args) {
        Foo f1 = newBuilder().a(1).b(2).c(3).build();
        Foo f2 = newBuilder().a(1).b(2).c(3).a(4).build();
    }

}

Antworten auf die Frage(5)

Ihre Antwort auf die Frage