Java 通用生成器
Java generic builder
假设我需要一些 DerivedBuilder
来扩展一些 BaseBuilder
。基础构建器有一些方法,如 foo
(returns BaseBuilder
)。派生生成器具有方法 bar
。方法 bar
应在方法 foo
之后调用。为了做到这一点,我可以像这样覆盖 DerivedBuilder
中的 foo
方法:
@Override
public DerivedBuilder foo() {
super.foo();
return this;
}
问题是 BaseBuilder
有很多像 foo
这样的方法,我必须重写它们中的每一个。我不想那样做,所以我尝试使用泛型:
public class BaseBuilder<T extends BaseBuilder> {
...
public T foo() {
...
return (T)this;
}
}
public class DerivedBuilder<T extends DerivedBuilder> extends BaseBuilder<T> {
public T bar() {
...
return (T)this;
}
}
但问题是我还是写不出来
new DerivedBuilder<DerivedBuilder>()
.foo()
.bar()
虽然T
这里是DerivedBuilder
。我该怎么做才能不覆盖很多功能?
我从你的问题中了解到,foo()方法应该在bar()方法之前执行。
如果正确,您可以应用模板设计模式。
在BaseBuilder中创建一个抽象方法bar。
还有一个新方法说 'template'。方法模板将定义序列 - 首先执行 foo(),然后执行 bar()。
DerivedBuilder 将提供方法 bar 的实现。
public abstract class BaseBuilder {
public void foo(){
System.out.println("foo");
}
public abstract void bar();
public void template(){
foo();
bar();
}
}
public class DerivedBuilder extends BaseBuilder{
@Override
public void bar() {
System.out.println("bar");
}
public static void main(String[] args) {
BaseBuilder builder = new DerivedBuilder();
builder.template();
}
}
希望这有帮助。
你的问题是DerivedBuilder
的定义:
class DerivedBuilder<T extends DerivedBuilder>;
然后用类型擦除参数实例化它new DerivedBuilder<DerivedBuilder<...what?...>>()
。
您需要一个完全定义的派生类型,如下所示:
public class BaseBuilder<T extends BaseBuilder<T>> {
@SuppressWarnings("unchecked")
public T foo() {
return (T)this;
}
}
public class DerivedBuilder extends BaseBuilder<DerivedBuilder> {
public DerivedBuilder bar() {
return this;
}
}
检查ideone.com。
我在这里做了 Class.cast(this)
,而不是铸造 return (T) this;
。
实现:
BaseBuilder.build(ExtendedBuilder.class).foo().bar().foo().bar();
层次结构中的每个 class 都需要知道实际的最终 child class,因此我选择制作一个 工厂方法 build
在基地 class.
this
到实际 child 的转换也是在基础 class 的最终方法中完成的,提供 return me();
.
class BaseBuilder<B extends BaseBuilder<B>> {
protected Class<B> type;
public static <T extends BaseBuilder<T>> T build(Class<T> type) {
try {
T b = type.newInstance();
b.type = type;
return b;
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
protected final B me() {
return type.cast(this);
}
B foo() {
System.out.println("foo");
return me();
}
}
class ExtendedBuilder extends BaseBuilder<ExtendedBuilder> {
ExtendedBuilder bar() {
System.out.println("bar");
return me();
}
}
除了,如果你想进一步嵌套,可以使用这个:
class Base<T extends Base<?>> {
public T alpha() { return (T) this; }
public T bravo() { return (T) this; }
public T foxtrot() { return (T) this; }
}
class Derived<T extends Derived<?>> extends Base<T> {
public T charlie() { return (T) this; }
public T golf() { return (T) this; }
}
class FurtherDerived<T extends FurtherDerived<?>> extends Derived<T> {
public T delta() { return (T) this; }
public T hotel() { return (T) this; }
}
class MuchFurtherDerived<T extends MuchFurtherDerived<?>> extends FurtherDerived<T> {
public T echo() { return (T) this; }
}
public static void main(String[] args) {
new MuchFurtherDerived<MuchFurtherDerived<?>>()
.alpha().bravo().charlie().delta().echo().foxtrot().golf().hotel()
.bravo().golf().delta().delta().delta().hotel().alpha().echo()
.echo().alpha().hotel().foxtrot();
}
假设我需要一些 DerivedBuilder
来扩展一些 BaseBuilder
。基础构建器有一些方法,如 foo
(returns BaseBuilder
)。派生生成器具有方法 bar
。方法 bar
应在方法 foo
之后调用。为了做到这一点,我可以像这样覆盖 DerivedBuilder
中的 foo
方法:
@Override
public DerivedBuilder foo() {
super.foo();
return this;
}
问题是 BaseBuilder
有很多像 foo
这样的方法,我必须重写它们中的每一个。我不想那样做,所以我尝试使用泛型:
public class BaseBuilder<T extends BaseBuilder> {
...
public T foo() {
...
return (T)this;
}
}
public class DerivedBuilder<T extends DerivedBuilder> extends BaseBuilder<T> {
public T bar() {
...
return (T)this;
}
}
但问题是我还是写不出来
new DerivedBuilder<DerivedBuilder>()
.foo()
.bar()
虽然T
这里是DerivedBuilder
。我该怎么做才能不覆盖很多功能?
我从你的问题中了解到,foo()方法应该在bar()方法之前执行。
如果正确,您可以应用模板设计模式。
在BaseBuilder中创建一个抽象方法bar。
还有一个新方法说 'template'。方法模板将定义序列 - 首先执行 foo(),然后执行 bar()。
DerivedBuilder 将提供方法 bar 的实现。
public abstract class BaseBuilder {
public void foo(){
System.out.println("foo");
}
public abstract void bar();
public void template(){
foo();
bar();
}
}
public class DerivedBuilder extends BaseBuilder{
@Override
public void bar() {
System.out.println("bar");
}
public static void main(String[] args) {
BaseBuilder builder = new DerivedBuilder();
builder.template();
}
}
希望这有帮助。
你的问题是DerivedBuilder
的定义:
class DerivedBuilder<T extends DerivedBuilder>;
然后用类型擦除参数实例化它new DerivedBuilder<DerivedBuilder<...what?...>>()
。
您需要一个完全定义的派生类型,如下所示:
public class BaseBuilder<T extends BaseBuilder<T>> {
@SuppressWarnings("unchecked")
public T foo() {
return (T)this;
}
}
public class DerivedBuilder extends BaseBuilder<DerivedBuilder> {
public DerivedBuilder bar() {
return this;
}
}
检查ideone.com。
我在这里做了 Class.cast(this)
,而不是铸造 return (T) this;
。
实现:
BaseBuilder.build(ExtendedBuilder.class).foo().bar().foo().bar();
层次结构中的每个 class 都需要知道实际的最终 child class,因此我选择制作一个 工厂方法 build
在基地 class.
this
到实际 child 的转换也是在基础 class 的最终方法中完成的,提供 return me();
.
class BaseBuilder<B extends BaseBuilder<B>> {
protected Class<B> type;
public static <T extends BaseBuilder<T>> T build(Class<T> type) {
try {
T b = type.newInstance();
b.type = type;
return b;
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
protected final B me() {
return type.cast(this);
}
B foo() {
System.out.println("foo");
return me();
}
}
class ExtendedBuilder extends BaseBuilder<ExtendedBuilder> {
ExtendedBuilder bar() {
System.out.println("bar");
return me();
}
}
除了
class Base<T extends Base<?>> {
public T alpha() { return (T) this; }
public T bravo() { return (T) this; }
public T foxtrot() { return (T) this; }
}
class Derived<T extends Derived<?>> extends Base<T> {
public T charlie() { return (T) this; }
public T golf() { return (T) this; }
}
class FurtherDerived<T extends FurtherDerived<?>> extends Derived<T> {
public T delta() { return (T) this; }
public T hotel() { return (T) this; }
}
class MuchFurtherDerived<T extends MuchFurtherDerived<?>> extends FurtherDerived<T> {
public T echo() { return (T) this; }
}
public static void main(String[] args) {
new MuchFurtherDerived<MuchFurtherDerived<?>>()
.alpha().bravo().charlie().delta().echo().foxtrot().golf().hotel()
.bravo().golf().delta().delta().delta().hotel().alpha().echo()
.echo().alpha().hotel().foxtrot();
}