Builder Pattern and Inheritance

后端 未结 8 511
攒了一身酷
攒了一身酷 2020-11-29 19:01

I have an object hierarchy that increases in complexity as the inheritance tree deepens. None of these are abstract, hence, all of their instances serve a, more or less soph

8条回答
  •  盖世英雄少女心
    2020-11-29 19:47

    I did some experimenting and I found this to work quite nicely for me. Note that I prefer to create the actual instance at the start and the call all the setters on that instance. This is just a preference.

    The main differences with the accepted answer is that

    1. I pass a parameter that indicated the return type
    2. There is no need for an Abstract... and a final builder.
    3. I create a 'newBuilder' convenience method.

    The code:

    public class MySuper {
        private int superProperty;
    
        public MySuper() { }
    
        public void setSuperProperty(int superProperty) {
            this.superProperty = superProperty;
        }
    
        public static SuperBuilder newBuilder() {
            return new SuperBuilder<>(new MySuper());
        }
    
        public static class SuperBuilder> {
            private final R mySuper;
    
            public SuperBuilder(R mySuper) {
                this.mySuper = mySuper;
            }
    
            public B withSuper(int value) {
                mySuper.setSuperProperty(value);
                return (B) this;
            }
    
            public R build() {
                return mySuper;
            }
        }
    }
    

    and then a subclass look like this:

    public class MySub extends MySuper {
        int subProperty;
    
        public MySub() {
        }
    
        public void setSubProperty(int subProperty) {
            this.subProperty = subProperty;
        }
    
        public static SubBuilder newBuilder() {
            return new SubBuilder(new MySub());
        }
    
        public static class SubBuilder>
            extends SuperBuilder {
    
            private final R mySub;
    
            public SubBuilder(R mySub) {
                super(mySub);
                this.mySub = mySub;
            }
    
            public B withSub(int value) {
                mySub.setSubProperty(value);
                return (B) this;
            }
        }
    }
    

    and a subsub class

    public class MySubSub extends MySub {
        private int subSubProperty;
    
        public MySubSub() {
        }
    
        public void setSubSubProperty(int subProperty) {
            this.subSubProperty = subProperty;
        }
    
        public static SubSubBuilder newBuilder() {
            return new SubSubBuilder<>(new MySubSub());
        }
    
        public static class SubSubBuilder>
            extends SubBuilder {
    
            private final R mySubSub;
    
            public SubSubBuilder(R mySub) {
                super(mySub);
                this.mySubSub = mySub;
            }
    
            public B withSubSub(int value) {
                mySubSub.setSubSubProperty(value);
                return (B)this;
            }
        }
    
    }
    

    To verify it fully works I used this test:

    MySubSub subSub = MySubSub
            .newBuilder()
            .withSuper (1)
            .withSub   (2)
            .withSubSub(3)
            .withSub   (2)
            .withSuper (1)
            .withSubSub(3)
            .withSuper (1)
            .withSub   (2)
            .build();
    

提交回复
热议问题