Как улучшить шаблон строителя?
Недавно я искал способ инициализации сложного объекта без передачи большого количества параметров конструктору. Я попробовал это с шаблоном компоновщика, но мне не нравится тот факт, что я не могу проверить во время компиляции, действительно ли я установил все необходимые значения.
Традиционный образец строителяКогда я использую шаблон строителя, чтобы создать свойComplex
объект, создание более «безопасное», потому что легче увидеть, для чего используется аргумент:
new ComplexBuilder()
.setFirst( "first" )
.setSecond( "second" )
.setThird( "third" )
...
.build();
Но сейчас у меня проблема, что я могу легко пропустить важный параметр. Я могу проверить это внутриbuild()
метод, но это только во время выполнения. Во время компиляции нет ничего, что предупреждает меня, если я что-то пропустил.
Теперь моя идея заключалась в том, чтобы создать конструктор, который «напоминает» мне, если я пропустил необходимый параметр. Моя первая попытка выглядит так:
public class Complex {
private String m_first;
private String m_second;
private String m_third;
private Complex() {}
public static class ComplexBuilder {
private Complex m_complex;
public ComplexBuilder() {
m_complex = new Complex();
}
public Builder2 setFirst( String first ) {
m_complex.m_first = first;
return new Builder2();
}
public class Builder2 {
private Builder2() {}
Builder3 setSecond( String second ) {
m_complex.m_second = second;
return new Builder3();
}
}
public class Builder3 {
private Builder3() {}
Builder4 setThird( String third ) {
m_complex.m_third = third;
return new Builder4();
}
}
public class Builder4 {
private Builder4() {}
Complex build() {
return m_complex;
}
}
}
}
Как видите, каждый установщик класса построителя возвращает свой внутренний класс построителя. Каждый внутренний класс построителя предоставляет ровно один метод установки, а последний предоставляет только метод build ().
Теперь конструкция объекта снова выглядит так:
new ComplexBuilder()
.setFirst( "first" )
.setSecond( "second" )
.setThird( "third" )
.build();
... но нет способа забыть необходимый параметр. Компилятор не примет это.
Необязательные параметрыЕсли бы у меня были необязательные параметры, я бы использовал последний внутренний класс построителяBuilder4
установить их, как это делает «традиционный» строитель, возвращая себя.