【问题标题】:Abstract class for builder pattern构建器模式的抽象类
【发布时间】:2018-05-13 08:44:12
【问题描述】:

我现有的模型类总是使用这样的构建器模式:

public class Model {
    public static class Builder {
        private boolean isValid;
        private List<String> errorMessagesOrNull;

        public Builder setIsValid(final boolean isValid) {
            this.isValid = isValid;
            return this;
        }

        public Builder setErrorMessages(final List<String> errorMessages) {
            this.errorMessagesOrNull = errorMessages;
            return this;
        }

        public List<String> getErrorMessages() {
            return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
        }

        public Model Build() {
            return new Model(this);
        }
    }

    private boolean isValid;
    private List<String> errorMessages;

    private Model(final Builder builder) {
        this.isValid = builder.isValid;
        this.errorMessages = builder.getErrorMessages();
    }

    public boolean getIsValid() {
        return isValid;
    }

    public List<String> getErrorMessages() {
        return errorMessages;
    }
}

如您所见,模型类始终具有isValiderrorMessages。我想写一个抽象类来最小化那些模型类的重复逻辑。

所以我想出了这个抽象类:

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;

    private AbstractModel(final Builder<T> builder) {
        this.isValid = builder.isValid;
        this.errorMessages = builder.getErrorMessages();
    }

    public boolean getIsValid() {
        return isValid;
    }

    public List<String> getErrorMessages() {
        return errorMessages;
    }
}

但它并没有真正按我的预期工作。当我扩展抽象类时:

public class Model extends AbstractModel<Model> {
    // Empty here since all fields are extended
}

我不能这样做:

Model model = new Model.Builder.setIsValid(true).Build();

我希望抽象类有Builder静态类,这样就不用每次都写静态类Builder了。

请指教。

【问题讨论】:

  • Model 类甚至没有 extend AbstractModel&lt;T extends AbstractModel&gt; 类。
  • @Theikon 我更新了问题 - 抱歉,请看一下
  • 你为什么要把它变成内部的和静态的?
  • 我猜这只是我的偏好@YassinHajaj

标签: java design-patterns abstract-class


【解决方案1】:

您还需要实现Builder

public class Model extends AbstractModel<Model>{


    private Model(final Builder builder) {
        super(builder);
    }

    public static class Builder2 extends AbstractModel.Builder<Model> {

        @Override
        public Model Build() {
            return new Model(this);
        }
    }
}

那么就可以调用

Model model = new Model.Builder2().Build();

编辑

另外,AbstractBuilder 的构造函数也必须是protected

  protected AbstractModel(final Builder<? extends Builder<T>> builder) {
        this.isValid = builder.isValid;
        this.errorMessages = builder.getErrorMessages();
    }

【讨论】:

  • 谢谢!这正是我一直在寻找的。而且我不需要protected AbstractModel(final Builder&lt;? extends Builder&lt;T&gt;&gt; builder) {...} - 我只有protected AbstractModel(final Builder&lt;T&gt; builder) {...},它工作正常。非常感谢。
【解决方案2】:

我认为你的逻辑有很大的缺陷。该程序本身根本没有任何意义。为什么首先要构造一个带有Builder 类的Model?我认为最好向你展示你应该如何编写你的程序,而不是仅仅将它“绑定”在一起。好的,让我们从Model 类开始。

假设没有Builder 就无法构造Model 类。那么将Builder 类添加到Model 类中是否有意义?简短的回答:不,不会。相反,Builder 类应包含 Model 类作为非静态内部类。

/**
 * The {@code Builder} can construct new instances of the {@code Model} class.
 *
 * @see Model
 */
public class Builder
{
    private final String[] log;

    /**
     * The {@code Model} class can do something. You can only construct it through a {@code Builder}.
     *
     * @see Builder
     */
    public class Model
    {
        private final Builder builder;

        /**
         * Constructs a new {@code Model} with the specified argument.
         *
         * @param builder the {@code Builder} that constructed the model.
         */
        public Model(final Builder builder)
        {
            this.builder = builder;
        }

        /**
         * Returns the associated {@code Builder}.
         *
         * @return the builder that constructed the model.
         */
        public Builder getBuilder()
        {
            return this.builder;
        }
    }

    /**
     * Constructs a new instance of the {@code Builder} class with the specified argument.
     *
     * @param log the log of the {@code Builder}.
     */
    public Builder(final String... log)
    {
        this.log = log;
    }

    /**
     * Tries to {@code build} a new instance of the {@code Model} class.
     *
     * @return the constructed {@code Model}.
     */
    public Model build()
    {
        return new Model(this);
    }

    /**
     * Returns the log of the {@code Builder}.
     *
     * @return an log.
     */
    public String[] getLog()
    {
        return this.log;
    }

    /**
     * Determines whether or not the {@code Builder} is valid.
     *
     * @return {@code true} when the specified {@code log} is not {@code null}; {@code false} otherwise.
     */
    public boolean isValid()
    {
        return this.log != null;
    }
}

Builder 之外的任何类都不能构造Model。但是,如果您构造Builder 类的新实例并获得调用build 方法的结果,您将可以访问所有public 变量和方法。

如果你知道要构造一个Model,你可以这样做:

Builder.Model model = new Builder().build();

如果您不想要 Builder. 前缀,只需添加导入 Model 类的 import 语句。

import organisation.projectname.pathToBuilder.Builder.Model;

【讨论】:

  • 感谢您的回复 - 但 Model 类存在错误:Implicit super constructor AbstractModel&lt;Model&gt;() is undefined for default constructor. Must define an explicit constructor。我做错了什么?
  • 没关系!请教育我:D
  • 感谢您的建议!我将不同的帖子标记为答案,因为它与原始问题更相关。但我也赞成你的回答。我真的很感谢你的帖子:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多