Наследование Java с использованием шаблона builder
у меня 3 класса:
- ShellError
- WebError
здесь
ShellError extends Error
и
WebError extends Error
на ShellError
есть поля, некоторые из которых являются обязательными, а остальные являются обязательными. Я строю объект следующим образом:
shellError = new ShellError.Builder().setFile(filePattern)
.setHost(host).setPath(path).setSource(file.isSource())
.setJobName(p.getJobName()).build();
С ShellError
выходит Error
, Я:
shellError.setDescription(msg.toString());
shellError.setExceptionClass("MyEvilException");
shellError.setExceptionMessage("Some clever error message");
shellError.setStacktrace(stack);
так ... зачем возиться со Строителем? Мне нравится тот факт, что моя build () среди прочего удобно проверяет, что все поля установлены соответствующим образом и т. д.
Я бы с удовольствием, если бы мог .. build ()ShellError
и добавьте к нему поля из Error
класса.
что я сделал работает.
- вопрос:
есть ли лучший способ, или есть ли смысл, что я сделал?
-- EDIT
я обновил Builder () до примите некоторые из параметров, которые ранее были в классе ошибок. Теперь у меня есть
shellError = new ShellError.Builder(exception, "Some description").setFile(filePattern).setHost(host)
.setPath(path).setSource(file.isSource()).
setJobName(p.getJobName()).build();
что скажешь? лучше? Хуже?
3 ответов
основываясь на функциях, на которые вы ссылались, это явно не стандартный java.ленг.Ошибка класса. Как правило, строители используются, чтобы позволить легко построить неизменяемый объект или обеспечить функциональность, подобную "именованным параметрам", в случаях, когда есть много параметров конфигурации / конструкции.
для этого конкретного случая было бы разумнее, если бы класс ошибок был неизменяемым после построения, и если бы эти дополнительные сеттеры функции находились в конструкторе, а не в классе ошибок. Я не знаю, насколько вы контролируете любой из этих классов, но если вы можете их изменить, я бы предложил сначала сделать так, чтобы построитель поддерживал те же сеттеры, поэтому вы можете сделать всю конфигурацию в построителе. Затем, если это возможно, вы можете попробовать удалить эти методы сеттера и вместо этого разрешить их настройку из конструктора. Если у вас нет никакого контроля над ними, вы можете потенциально расширьте класс builder другим, который поддерживает эти дополнительные методы.
то, что вы сделали, имеет смысл. Похоже, что дизайн классов builder и error не обязательно имеет смысл, заставляя вас писать код, который кажется неэлегантным или непоследовательным.
на шаблона, популяризированный Джош блох, имеет преимущества, но он не работает так элегантно на родительских / подклассах, как описано в это обсуждение нашими коллегами в мире c#. Лучшее решение, которое я видел до сих пор, это этот (или легкий вариант of it).
Как уже было сказано, шаблон builder не является тем, что может органично вписаться в существующую политику инициализации объектов Java. Существует несколько подходов к достижению требуемого результата. Хотя, конечно, всегда лучше избегать любых двусмысленных практик, это не всегда возможно. Мой Хак основан на API отражения Java с дженериками:
abstract public class AbstractClass {
public static class Builder {
public <T extends AbstractClass> T build(Class<T> implementingClass) {
try {
Constructor<T> constructor = implementingClass
.getConstructor(new Class[]{Builder.class});
return constructor.newInstance(this);
} catch (NoSuchMethodException e) {
// TODO handle the exception
} catch (InvocationTargetException | InstantiationException |
IllegalAccessException e) {
// TODO handle the exception
}
}
}
protected AbstractClass(Builder builder) {
}
}
public class ImplementingClass extends AbstractClass {
public ImplementingClass (Builder builder) {
super(builder);
}
}
инициализации:
ImplementingClass instance = new AbstractClass.Builder()
.build(ImplementingClass.class);