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代码,这时会遇到一些语法上的困难。
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;
}