Еще один день и еще одна борьба с дженериками.Java свободно строитель и наследование
Я набор Control
объектов с помощью следующего дерева наследования:
BaseControl
|_SimpleControl
|_MultipleControl
|_AutocompleteControl
|_SelectControl
Для каждого из неабстрактного объекта в этом дереве я хотел бы предоставить строитель, так что эти объекты могут быть созданы легко. Вот то, что я до сих пор:
BaseControlBuilder:
public abstract class BaseControlBuilder<C extends BaseControl, B extends BaseControlBuilder<C, B>> {
protected C control;
private B builder;
BaseControlBuilder() {
control = createObj();
builder = getThis();
}
public C build() { return control; }
protected abstract C createObj();
protected abstract B getThis();
}
SimpleControlBuilder:
public class SimpleControlBuilder<C extends SimpleControl, B extends SimpleControlBuilder<C, B>>
extends BaseControlBuilder<SimpleControl, SimpleControlBuilder<C, B>> {
public SimpleControlBuilder(final String id, final String caption,
final InputType controlType) {
super();
control.setId(id);
control.setCaption(caption);
control.setType(controlType);
}
public SimpleControlBuilder(final InputType controlType) {
this("", "", controlType);
}
public SimpleControlBuilder(final Enum<?> en, final InputType controlType) {
this(en.name(), en.toString(), controlType);
}
public SimpleControlBuilder<C, B> disabled() {
control.setDisabled(true);
return this;
}
@Override
protected SimpleControl createObj() {
return new SimpleControl();
}
@Override
protected SimpleControlBuilder<C, B> getThis() {
return this;
}
}
MultipleControlBuilder:
abstract class MultipleControlBuilder<C extends MultipleControl, B extends MultipleControlBuilder<C, B>>
extends SimpleControlBuilder<MultipleControl, MultipleControlBuilder<C, B>> {
MultipleControlBuilder(final InputType type) {
super(type);
}
MultipleControlBuilder(final String id, final String caption,
final InputType type) {
super(id, caption, type);
}
MultipleControlBuilder(final Enum<?> en, final InputType type) {
super(en, type);
}
public MultipleControlBuilder<C, B> multiple() {
((MultipleControl) control).setMultiple(true);
return this;
}
}
AutocompleteControlBuilder:
public class AutocompleteControlBuilder<C extends AutocompleteControl, B extends AutocompleteControlBuilder<C, B>>
extends MultipleControlBuilder<AutocompleteControl, AutocompleteControlBuilder<C, B>> {
public AutocompleteControlBuilder(final String url,
final AutocompleteType autocompleteType) {
this("", "", url, autocompleteType);
}
public AutocompleteControlBuilder(final String id,
final String caption, final String url,
final AutocompleteType autocompleteType) {
super(id, caption, InputType.AUTOCOMPLETE);
((AutocompleteControl) control).setAutocompleteUrl(url);
((AutocompleteControl) control).setAutocompleteType(autocompleteType);
}
public AutocompleteControlBuilder(final Enum<?> en, final String url,
final AutocompleteType autocompleteType) {
this(en.name(), en.toString(), url, autocompleteType);
}
@Override
protected AutocompleteControl createObj() {
return new AutocompleteControl();
}
@Override
protected AutocompleteControlBuilder<C, B> getThis() {
return this;
}
}
Но удивительно, что у меня есть неожиданные результаты.
Например, в следующем коде я должен бросить control
в MultipleControl
назвать сеттер, несмотря на то, что C extends MultipleControl
...
Кроме того, следующий build()
вызов метода: new AutocompleteControlBuilder<AutocompleteControl, AutocompleteControlBuilder>("url", AutocompleteType.STANDARD).build());
возвращает SimpleControl
вместо AutocompleteControl
, который не делает смысл, потому что я явно предоставил параметр типа.
И последняя солома - это то, что краткость и четкий код, который я пытаюсь достичь, убиты уродливым вызовом конструктора new AutocompleteControlBuilder<AutocompleteControl, AutocompleteControlBuilder>
. Может ли кто-нибудь указать мне на лучшие методы решения этой проблемы?
Могу ли я спросить, почему у вас есть поле '' 'builder'''? Я не вижу, как вы его используете. Java уже имеет ковариантные типы возвращаемых данных, на первый взгляд, я бы сказал, что вы можете удалить оба параметра типа, поскольку оба они кажутся деталями реализации. Это действительно зависит от использования, хотя ... –
У меня есть быстрый вопрос об этой настройке @ mr.nothing, вам действительно нужно, чтобы SimpleControl был не абстрактный? – EpicPandaForce
Хм, JavaFX тоже начал с строителей, и в наши дни без них. Так что строители _can_ имеют стилистические недостатки. В вашем случае: меньше конструкторов, фабричный метод в самом классе управления ('RadioButton.create(). Label (« not me »).build(): ') –