You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

建造者模式抽象类设计问题:子类无法调用父类静态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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:22:27