多态对象层次结构的构建器模式:Java 可能吗? [英] Builder pattern for polymorphic object hierarchy: possible with Java?
问题描述
我有一个接口层次结构,Child
实现了 Parent
.我想使用不可变对象,所以我想设计 Builder
类来方便地构造这些对象.但是,我有很多Child
接口,我不想在每种类型的子构建器中重复构建Parent
的代码.
I have a hierarchy of interfaces, with Child
implementing Parent
. I would like to work with immutable objects, so I would like to design Builder
classes that construct these objects conveniently. However, I have many Child
interfaces, and I don't want to repeat the code for building Parent
s in each type of child builder.
因此,假设以下定义:
public interface Parent {
public Long getParentProperty();
}
public interface Child1 extends Parent {
public Integer getChild1Property();
}
public interface Child2 extends Parent {
public String getChild2PropertyA();
public Object getChild2PropertyB();
}
如何有效地实现构建器 Child1Builder
和 Child2Builder
?他们应该支持如下操作:
How can I efficiently implement builders Child1Builder
and Child2Builder
? They should support operation like:
Child1 child1 = Child1Builder.newChild1().withChild1Property(5).withParentProperty(10L);
和
Child2 child2 = Child2Builder.newChild2().withChild2PropertyA("Hello").withParentProperty(10L).withChild2PropertyB(new Object());
我不想为每个子构建器实现 withParentProperty
的特殊情况.
I don't want to implement a special case of withParentProperty
for each child builder.
编辑为 Child2
添加第二个属性,以阐明这不能通过简单的泛型来完成.我不是在寻找一种结合 Child1
和 Child2
的方法 - 我正在寻找一种方法来实现一个不重复的 Builder
系统为每个子类构建父类的工作.
Edited to add second property to Child2
to clarify that this cannot be done with simple generics. I am not looking for a way to combine Child1
and Child2
- I am looking for a way to implement a Builder
system that does not duplicate the work of building the parent class for every child class.
感谢您的帮助!
推荐答案
我想象的解决方案就像 Curiously Recurring Template模式,或CRTP.您可以定义一个基类来处理与父相关的初始化,但您仍然可能会发现两个样板getParent()
和 getThis()
方法在每个派生的与子相关的构建器类.
The solution I imagine is like the Curiously Recurring Template Pattern, or CRTP. You can define a base class to handle the parent-related initialization, but you still may find the two boilerplate getParent()
and getThis()
methods to be too much repetition in each derived child-related builder class.
看一看:
abstract class ParentBase implements Parent
{
@Override
public final Long getParentProperty()
{
return parentProperty_;
}
protected void setParentProperty(Long value)
{
parentProperty_ = value;
}
private Long parentProperty_;
}
abstract class ParentBuilder<T extends ParentBuilder<T>>
{
T withParentProperty(Long value)
{
getParent().setParentProperty(value);
return getThis();
}
protected abstract ParentBase getParent();
protected abstract T getThis();
}
final class ConcreteChild1 extends ParentBase implements Child1
{
@Override
public Integer getChild1Property()
{
return childProperty_;
}
public void setChild1Property(Integer value)
{
childProperty_ = value;
}
private Integer childProperty_;
}
final class Child1Builder extends ParentBuilder<Child1Builder>
{
public Child1Builder()
{
pending_ = new ConcreteChild1();
}
public Child1Builder withChild1Property(Integer value)
{
pending_.setChild1Property(value);
return this;
}
@Override
protected ParentBase getParent()
{
return pending_;
}
@Override
protected Child1Builder getThis()
{
return this;
}
private final ConcreteChild1 pending_;
}
如您所见,ParentBuilder
类型期望与派生类型合作以允许它返回正确类型的实例.它自己的this
引用不会到期,因为ParentBuilder
中this
的类型当然是ParentBuilder
,而不是说 Child1Builder
旨在维护流畅"的调用链.
As you can see, the ParentBuilder
type expects to be cooperating with a derived type to allow it to return a properly-typed instance. Its own this
reference won't due, because the type of this
within ParentBuilder
is, of course, ParentBuilder
, and not, say, Child1Builder
as intended to maintain the "fluent" call chaining.
我将getThis()
技巧"归功于 Angelika Langer 的教程入口.
I owe the "getThis()
trick" to Angelika Langer's tutorial entry.
这篇关于多态对象层次结构的构建器模式:Java 可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!