美文网首页程序员
Java (Fluent)Builder模式的继承

Java (Fluent)Builder模式的继承

作者: 黄大海 | 来源:发表于2018-06-26 19:56 被阅读999次

    Fluent风格的代码十分流行,应用在Builder模式中也很常见,下面是一个简单的例子:

    public class FluentBuilder {
        private String param1;
        private String param2;
        
        public FluentBuilder setParam1(String param1){
            this.param1 = param1;
            return this;
        }
        
        public FluentBuilder setParam2(String param2){
            this.param2 = param2;
            return this;
        }
        
        public String build(){
            return param1 + param2;
        }
    }
    
    

    使用起来很简洁:

            String result = new FluentBuilder()
                .setParam1("1")
                .setParam2("2")
                .build();
    

    有时候对于具有相关对象的构造,需要复用builder代码,这时会遇到一些语法上的困难。

    • 子类Builder:
    public class SubFluentBuilder extends FluentBuilder {
        private String param3;
        
        public SubFluentBuilder setParam3(String param3){
            this.param3 = param3;
            return this;
        } 
    }
    
    • 如果先调用子类方法,再调父类方法,则不会有问题
            String result = new SubFluentBuilder()
                    .setParam3("3")
                    .setParam1("1")
                    .setParam2("2")
                    .build();
    
    • 但是父类方法在子类之前,则子类方法不再可见:
            String result = new SubFluentBuilder()
                    .setParam1("1")
                    .setParam2("2")
                    .setParam3("3")//编译错误,无法找到该方法
                    .build();
    
    • 原因在于 SubFluentBuilder.setParam2() 返回的是 FluentBuilder, 而它是不具备子类方法的。

    这里有两个解决方案

    第一种是通过泛型来获得子类类型,返回this强制转换成子类。 这时无论子类、父类都返回子类builder,所有方法可用。
    public class GenericBuilder<T extends GenericBuilder<T>> {
        private String param1;
        private String param2;
        
        public T setParam1(String param1){
            this.param1 = param1;
            return (T)this;
        }
        
        public T setParam2(String param2){
            this.param2 = param2;
            return (T)this;
        }
        
        public String build(){
            return param1 + param2;
        }
    }
    
    public class SubGenericBuilder extends GenericBuilder<SubGenericBuilder> {
        private String param3;
        
        public SubGenericBuilder setParam3(String param3){
            this.param3 = param3;
            return this;
        } 
    }
    
    第二种方案就是重写所有父类方法,使之返回子类类型, JDK中StringBuilder/StringBuffer就是这样实现的 :
    public class SubFluentBuilder2 extends FluentBuilder {
        private String param3;
        
        public SubFluentBuilder2 setParam1(String param1){
            super.setParam1(param1);
            return this;
        }
        
        public SubFluentBuilder2 setParam2(String param2){
            super.setParam2(param2);
            return this;
        }
        
        public SubFluentBuilder2 setParam3(String param3){
            this.param3 = param3;
            return this;
        } 
    

    相关文章

      网友评论

        本文标题:Java (Fluent)Builder模式的继承

        本文链接:https://www.haomeiwen.com/subject/syomyftx.html