In java, can you use the builder pattern with required and reassignable fields?

后端 未结 5 700
南笙
南笙 2021-01-20 01:57

This is related to the following question:

How to improve the builder pattern?

I\'m curious whether it\'s possible to implement a builder with the following

5条回答
  •  天涯浪人
    2021-01-20 02:18

    Building on Jordão's idea, I came up with the following, which may arguably satisfy all requirements 1-6 even though there is some duplicate code in the type parameters. Essentially, the idea is to "pass around" the return types of each method by using type parameters to override the return value of the inherited methods. Even though the code is verbose and impractical, and actually requires Omega(n^3) characters if you extend it out to an arbitrary number of fields n, I'm posting it because I think it's an interesting use of the java type system. If anyone can find a way to reduce the number of type parameters (especially asymptotically), please post in the comments or write another answer.

    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, ? extends BuilderC> newBuilder() {
            return new BuilderFinal();
        }
    
        public static class BuilderA, C extends BuilderC> {
            private volatile int a;
    
            @SuppressWarnings("unchecked")
            public B a(int v) {
                a = v;
                return (B) this;
            }
    
            public int a() {
                return a;
            }
        }
    
        public static class BuilderB, C extends BuilderC> extends BuilderA {
            private volatile int b;
    
            @SuppressWarnings("unchecked")
            public C b(int v) {
                b = v;
                return (C) this;
            }
    
            public int b() {
                return b;
            }
        }
    
        public static class BuilderC, C extends BuilderC> extends BuilderB {
            private volatile int c;
    
            @SuppressWarnings("unchecked")
            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).a(2).build();
            Foo f2 = newBuilder().a(1).a(2).c(3).build(); // compile error
            Foo f3 = newBuilder().a(1).b(2).a(3).b(4).b(5).build(); // compile error
        }
    
    }
    

提交回复
热议问题