建造者模式抽象类设计问题:子类无法调用父类静态Builder
问题:复用带建造者模式的模型类逻辑时遇到的继承问题
你有多个模型类都包含isValid和errorMessages属性,一开始每个类都写了重复的建造者模式代码,于是想通过抽象类来复用这些重复逻辑,但发现子类无法直接调用抽象类里的静态Builder类,没法像预期那样链式创建实例。
问题根源
核心问题在于:静态成员(包括静态内部类)不会被子类继承。你写的AbstractModel里的Builder是静态内部类,所以Model子类并不会自动拥有这个Builder类,自然没法直接用new Model.Builder(...)来调用。
解决方案
我们需要让每个子类显式声明自己的Builder静态类,继承抽象类的Builder,这样既能复用父类里的setIsValid、setErrorMessages和getErrorMessages逻辑,又能实现创建子类实例的Build方法。
基础版实现
首先调整你的抽象类(仅需将构造器改为protected,让子类能调用):
public abstract class AbstractModel<T extends AbstractModel<T>> { public static abstract class Builder<T> { private boolean isValid; private List<String> errorMessagesOrNull; public Builder<T> setIsValid(final boolean isValid) { this.isValid = isValid; return this; } public Builder<T> setErrorMessages(final List<String> errorMessages) { this.errorMessagesOrNull = errorMessages; return this; } public List<String> getErrorMessages() { return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull; } public abstract T Build(); } private boolean isValid; private List<String> errorMessages; // 改为protected,允许子类构造器调用 protected AbstractModel(final Builder<T> builder) { this.isValid = builder.isValid; this.errorMessages = builder.getErrorMessages(); } public boolean getIsValid() { return isValid; } public List<String> getErrorMessages() { return errorMessages; } }
然后子类Model需要自己声明Builder类并实现Build方法:
public class Model extends AbstractModel<Model> { // 子类专属静态Builder,继承父类Builder public static class Builder extends AbstractModel.Builder<Model> { @Override public Model Build() { return new Model(this); } } // 私有构造器,仅允许Builder调用 private Model(Builder builder) { super(builder); // 调用父类构造器,复用属性赋值逻辑 } }
现在你就可以像预期那样调用了:
Model model = new Model.Builder().setIsValid(true).Build();
进阶版:优化链式调用(支持子类扩展)
如果后续你的子类Builder需要扩展自己的方法,基础版会有个小问题:调用父类的setIsValid后返回的是AbstractModel.Builder类型,没法直接链式调用子类的扩展方法。我们可以通过调整泛型来解决这个问题:
修改抽象类的Builder,加入泛型参数表示当前Builder类型:
public abstract class AbstractModel<T extends AbstractModel<T>> { // 新增泛型B表示当前Builder的类型,确保链式调用返回子类Builder public static abstract class Builder<B extends Builder<B, T>, T extends AbstractModel<T>> { private boolean isValid; private List<String> errorMessagesOrNull; // 辅助方法,返回当前Builder的实例(强制转换为子类类型) @SuppressWarnings("unchecked") protected B self() { return (B) this; } // 现在set方法返回的是B类型(子类Builder) public B setIsValid(final boolean isValid) { this.isValid = isValid; return self(); } public B setErrorMessages(final List<String> errorMessages) { this.errorMessagesOrNull = errorMessages; return self(); } public List<String> getErrorMessages() { return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull; } public abstract T Build(); } private boolean isValid; private List<String> errorMessages; protected AbstractModel(final Builder<?, T> builder) { this.isValid = builder.isValid; this.errorMessages = builder.getErrorMessages(); } public boolean getIsValid() { return isValid; } public List<String> getErrorMessages() { return errorMessages; } }
子类Model的Builder调整为:
public class Model extends AbstractModel<Model> { public static class Builder extends AbstractModel.Builder<Builder, Model> { // 子类扩展方法示例 public Builder setName(String name) { // 这里可以添加子类专属属性的赋值逻辑 return this; } @Override public Model Build() { return new Model(this); } } private Model(Builder builder) { super(builder); // 如果有子类专属属性,在这里完成赋值 } }
现在链式调用可以顺畅地混合父类和子类的方法:
Model model = new Model.Builder() .setIsValid(true) .setName("test model") // 子类扩展方法 .Build();
总结
- 静态内部类不会被子类继承,所以必须在子类中显式声明自己的
Builder并继承父类的Builder - 通过子类Builder实现
Build方法,创建当前子类的实例,同时子类构造器调用父类构造器复用属性赋值逻辑 - 如果需要支持子类Builder扩展方法,调整父类Builder的泛型,让set方法返回子类Builder类型,保证链式调用的流畅性
内容的提问来源于stack exchange,提问作者young-ceo
相关产品推荐
相关产品推荐

