java - Builder Factory 返回不同的子接口(interface)

标签 java generics factory builder

我知道堆栈溢出上有很多与此相关的变体和相关主题,但我还没有找到任何令人信服的答案,所以我自己尝试一下。

我正在尝试设计一个构建器工厂,它返回公共(public)构建器接口(interface)的不同子类。我希望允许所有实现共享一个公共(public)抽象类以供代码重用。

请注意,我对 build() 方法的返回类型不感兴趣,只对构建器的类型感兴趣。

这是我到目前为止所拥有的:

带有通用子接口(interface)的构建器接口(interface):

interface FruitBuilder<T extends FruitBuilder<T>> {
    T taste(String taste);
    T shape(String shape);
    T weight(String weight);

    Fruit build();
}

一些构建器还有其他方法:

interface GrapesBuilder extends FruitBuilder<GrapeBuilder> {
    GrapesBuilder clusterSize(int clusterSize);
}

下一步是指定返回特定构建器的工厂:

interface FruitBuilderFactory {
    GrapesBuilder grapes();
    AppleBuilder apple();
    LemonBuilder lemon();
}

这些界面的用户应该能够像这样使用它:

 Fruit grapes = fruitBuilderFactory
    .grapes()
    .weight(4)
    .color("Purple")
    .clusterSize(4)  // Note that the GrapesBuilder type must be accessible here!
    .build();

大部分逻辑将进入抽象类,包括高级构建逻辑:

abstract class BaseFruitBuilder<T extends FruitBuilder<T>> implements FruitBuilder<T> {

   String taste;

   T taste(String taste) {
       this.taste = taste;
       return (T)this;     // Ugly cast!!!!!
   }

   ...

    Fruit build() {
       Fruit fruit = createSpecificInstance();

       // Do a lot of stuff on the fruit instance.

       return fruit;
    }

    protected abstract Fruit createSpecificInstance();
}

给定基类,实现新的构建器非常简单:

class GrapseBuilderImpl extends BaseFruitBuilder<GrapesBuilder> {
   int clusterSize;
   GrapesBuilder clusterSize(int clusterSize) {
       this.clusterSize = clusterSize;
   }

   protected Fruit createSpecificInstance() {
       return new Grape(clusterSize);
   }
}

这一切都编译好了(至少是我真正的代码)。问题是我是否可以删除抽象类中对 T 的丑陋转换。

最佳答案

避免强制转换的一个选项是定义一个返回 T 的抽象方法。 :

abstract class BaseFruitBuilder<T extends FruitBuilder<T>> implements FruitBuilder<T> {

    String taste;

    T taste(String taste) {
       this.taste = taste;
       return returnThis();
    }

    protected abstract T returnThis();

     //...
}

class GrapseBuilderImpl extends BaseFruitBuilder<GrapesBuilder> {
    //...
    @Override
    protected T returnThis() {
        return this;
    }
}

缺点是您必须信任每个子类才能正确实现该方法。再说一次,按照你的方法,没有什么可以阻止任何人声明子类 GrapesBuilder extends BaseFruitBuilder<AppleBuilder> ,因此您需要在某种程度上信任子类。

编辑刚刚意识到这个解决方案被@user158037的comment引用。 。我自己也用过这个,但从未意识到这是一个众所周知的习语。 :-)

关于java - Builder Factory 返回不同的子接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32849499/

相关文章:

swift - 如何快速自动化工厂设计模式?

Java 泛型和多态性 - 如何在运行时缩小泛型类型范围

c# - 使代理/服务类更通用

python - 如何创建一个简单的元类?

php - eclipse pdt 中的代码完成和工厂模式

java - GWT RPC 延迟绑定(bind)失败

java - 隐藏按钮返回、主页、Android 应用程序

java - Postgres/hibernate 运算符不存在 : text = bytea

java - 是否可以使用 JAXB 从模式映射到 java.util.Map?

java - 比较两个类中不相等的集合