【问题标题】:How to write a reusable builder class with a flowing interface如何编写具有流动接口的可重用构建器类
【发布时间】:2017-10-01 20:20:46
【问题描述】:

我有几个类“X”和“Y”扩展了一个通用抽象类“Base”。几乎所有的配置都在 Base 中。由于配置可能很复杂并且需要灵活,我想为 X 和 Y 编写具有流动接口的 Builder 类。

在我看来,构建器中的大多数 setter 方法都是相同的——毕竟所有公共代码都在公共基类中。因此,我可能应该为“base”编写一个抽象的 Builder。这看起来像:

abstract class Base {
    abstract static class Builder {
        private int a;

        Builder setA(int a) {
           this.a = a;
           return this; 
        } 
    } 
}

public class X extends Base {
    static class Builder extends Base.Builder {
        X build() {
           // Do some stuff with the configuration
           return new X(); 
        } 
    } 
}

“Y”类看起来很像“X”

客户可以应该阅读

X x = new X.Builder().setA(1234).build();

但这行不通,因为setA() 返回一个Base.Builder,它没有实现build

我并不特别想重载派生构建器中的每个方法以返回正确的类型。这是很多样板代码和令人头疼的维护问题。

我可以使用泛型来告诉抽象构建器它的派生类是什么吗?

【问题讨论】:

  • 如果在基础构建器中创建抽象构建方法会怎样?

标签: java


【解决方案1】:

编辑:改进版 原始答案(见下文)不支持派生构建器添加额外的设置器。

是的,您可以为此使用泛型,但需要稍作改动。使用 Base.Builder 上的类型参数 T extends Builder,您允许派生的 Builder 指定应返回其类型。问题是 Base.Builder 中的 this 不一定满足该要求。因此,不必使用this 在设置器中返回,而是必须使用setBuilder 方法传递/设置要返回的正确构建器实例。派生的 Builder 必须确保在某些时候调用 super.setBuilder(this) 以确保 Base.Builder 已正确初始化:

abstract class Base {
    abstract static class Builder<T extends Builder> {
        private int a;
        private T builder;

        protected void setBuilder(T builder) {
            this.builder = builder;
        }

        T setA(int a) {
            this.a = a;
            return this.builder;
        }

    }
}

public class X extends Base {
    static class Builder extends Base.Builder<Builder> {

        public Builder() {
            super.setBuilder(this);
        }

        X build() {
            // Do some stuff with the configuration
            return new X();
        }
    }

    Builder builder() {
        return new Builder();
    }
}

原答案:

是的,您可以为此使用泛型。让builder类接受一个Type参数T extends Base,并为其添加一个抽象方法T build()

abstract class Base {
    abstract static class Builder<T extends Base> {
        private int a;

        Builder<T> setA(int a) {
            this.a = a;
            return this;
        }

        abstract T build();
    }
}

现在,扩展类可以向 Builder 指定它们的类型,并且只需要覆盖 build 方法,并且可以选择提供额外的 setter:

public class X extends Base {
    static class Builder extends Base.Builder<X> {
        X build() {
            // Do some stuff with the configuration
            return new X();
        }
    }
}

【讨论】:

  • 很好 - 谢谢 :-)
猜你喜欢
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 2014-09-17
  • 2014-02-07
  • 2015-04-10
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多