Java (Fluent)Builder模式的继承

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;
    } 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,929评论 18 399
  • 肖健雄(人称Professor X),创办了无人驾驶公司AutoX。作为80后计算机视觉领域的学术新星,机器视觉领...
    小赛TT阅读 14,535评论 0 2
  • 最近,我在追一部热播剧《我的前半生》,根据同名小说改编的电视剧中,每个人的角色都相当不错。子君和唐晶是最要...
    彼卟荏輸阅读 2,812评论 0 0
  • 对于我来说得过且过是现在最恰当的形容了,我自己,对!就是我自己! .我还相信世界会有奇迹的 小时候,总是幻...
    姓梁心不凉阅读 1,261评论 0 1