生成器工厂返回不同的子接口 [英] Builder Factory returning different sub-interfaces
问题描述
我知道堆栈溢出有很多变化和相关主题,但是我没有找到任何令人信服的答案,所以我自己去解决。
I know there are many variations and related topics to this one here on stack overflow but I haven't found any compelling answers so I'll give it a go myself.
我正在尝试设计一个构建器工厂,该工厂返回一个通用构建器接口的不同子类。我想允许所有实现共享一个通用的抽象类,以供代码重用。
I'm trying to design a builder factory that returns different subclasses of a common builder interface. I want to allow all the implementations to share a common abstract class for code re-use.
请注意,我对<$ c的返回类型不感兴趣$ c> build()方法,仅显示建筑商的类型。
Note that I'm not interested in the return type of the build()
method, only what types the builders are.
这是我到目前为止所拥有的:
This is what I have so far:
具有通用子接口的Builder接口:
Builder interface with generic for the sub-interfaces:
interface FruitBuilder<T extends FruitBuilder<T>> {
T taste(String taste);
T shape(String shape);
T weight(String weight);
Fruit build();
}
一些建筑商还有其他方法:
Some builders have additional methods:
interface GrapesBuilder extends FruitBuilder<GrapeBuilder> {
GrapesBuilder clusterSize(int clusterSize);
}
下一步是指定返回特定建造者的工厂:
Next is to specify a factory that returns the specific builders:
interface FruitBuilderFactory {
GrapesBuilder grapes();
AppleBuilder apple();
LemonBuilder lemon();
}
这些界面的用户应该可以像这样使用它:
A user of these interfaces should be able to use it like:
Fruit grapes = fruitBuilderFactory
.grapes()
.weight(4)
.color("Purple")
.clusterSize(4) // Note that the GrapesBuilder type must be accessible here!
.build();
大多数逻辑将进入抽象类,包括高级构建逻辑:
Most of the logic would go into the abstract class, including advanced build logic:
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();
}
鉴于基类,实现新构建器非常简单:
Given the base class, it's really simple to implement new builders:
class GrapseBuilderImpl extends BaseFruitBuilder<GrapesBuilder> {
int clusterSize;
GrapesBuilder clusterSize(int clusterSize) {
this.clusterSize = clusterSize;
}
protected Fruit createSpecificInstance() {
return new Grape(clusterSize);
}
}
这一切都是编译好的(至少我的真实码)。我是否可以删除抽象类中对T的丑陋转换的问题。
This is all compiling and fine (at least my real code). The question if whether or not I can remove the ugly cast to T in the abstract class.
推荐答案
避免转换的一种选择是定义返回 T
的单个抽象方法:
One option to avoid casting is to define a single abstract method returning 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扩展BaseFruitBuilder< AppleBuilder>
,因此您需要在某种程度上信任子类。
The downside is that you have to trust each subclass to implement the method correctly. Then again, with your approach, there's nothing stopping anyone from declaring a subclass GrapesBuilder extends BaseFruitBuilder<AppleBuilder>
, so you'll need to trust subclasses to some extent.
编辑刚刚意识到此解决方案已由@ user158037的评论。我自己使用过,但从未意识到这是已知的成语。 :-)
EDIT Just realized this solution was referenced by @user158037's comment. I've used this myself, but never realized it was a known idiom. :-)
这篇关于生成器工厂返回不同的子接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!