Builder Pattern and Inheritance

后端 未结 8 503
攒了一身酷
攒了一身酷 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:38

    Confronted with the same issue, I used the solution proposed by emcmanus at: https://community.oracle.com/blogs/emcmanus/2010/10/24/using-builder-pattern-subclasses

    I'm just recopying his/her preferred solution here. Let say we have two classes, Shape and Rectangle. Rectangle inherits from Shape.

    public class Shape {
    
        private final double opacity;
    
        public double getOpacity() {
            return opacity;
        }
    
        protected static abstract class Init> {
            private double opacity;
    
            protected abstract T self();
    
            public T opacity(double opacity) {
                this.opacity = opacity;
                return self();
            }
    
            public Shape build() {
                return new Shape(this);
            }
        }
    
        public static class Builder extends Init {
            @Override
            protected Builder self() {
                return this;
            }
        }
    
        protected Shape(Init init) {
            this.opacity = init.opacity;
        }
    }
    

    There is the Init inner class, which is abstract, and the Builder inner class, that is an actual implementation. Will be useful when implementing the Rectangle:

    public class Rectangle extends Shape {
        private final double height;
    
        public double getHeight() {
            return height;
        }
    
        protected static abstract class Init> extends Shape.Init {
            private double height;
    
            public T height(double height) {
                this.height = height;
                return self();
            }
    
            public Rectangle build() {
                return new Rectangle(this);
            }
        }
    
        public static class Builder extends Init {
            @Override
            protected Builder self() {
                return this;
            }
        }
    
        protected Rectangle(Init init) {
            super(init);
            this.height = init.height;
        }
    }
    

    To instantiate the Rectangle:

    new Rectangle.Builder().opacity(1.0D).height(1.0D).build();
    

    Again, an abstract Init class, inheriting from Shape.Init, and a Build that is the actual implementation. Each Builder class implement the self method, which is responsible to return a correctly cast version of itself.

    Shape.Init <-- Shape.Builder
         ^
         |
         |
    Rectangle.Init <-- Rectangle.Builder
    

提交回复
热议问题