В 2007 году я прочитал статью о том, как Джошуа Блохс рассматривает «шаблон строителя» и как его можно изменить, чтобы улучшить чрезмерное использование конструкторов и сеттеров, особенно когда объект имеет большое количество свойств, большинство из которыхявляются необязательными.Краткое описание этого шаблона проектирования изложено здесь [http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html].
. Мне понравилась идея, и я использую ее с тех пор.Проблема с этим, хотя он очень чистый и приятный в использовании с точки зрения клиента, его реализация может быть проблемой для задницы!В объекте так много разных мест, где одно свойство является ссылкой, и, таким образом, создание объекта и добавление нового свойства занимает много времени.
Итак ... У меня была идея.Во-первых, пример объекта в стиле Джошуа Блоха:
Джош Блох Стиль:
public class OptionsJoshBlochStyle {
private final String option1;
private final int option2;
// ...other options here <<<<
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private String option1;
private int option2;
// other options here <<<<<
public Builder() {
}
public Builder option1(String option1) {
this.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.option2 = option2;
return this;
}
public OptionsJoshBlochStyle build() {
return new OptionsJoshBlochStyle(this);
}
}
private OptionsJoshBlochStyle(Builder builder) {
this.option1 = builder.option1;
this.option2 = builder.option2;
// other options here <<<<<<
}
public static void main(String[] args) {
OptionsJoshBlochStyle optionsVariation1 = new OptionsJoshBlochStyle.Builder().option1("firefox").option2(1).build();
OptionsJoshBlochStyle optionsVariation2 = new OptionsJoshBlochStyle.Builder().option1("chrome").option2(2).build();
}
}
Теперь моя «улучшенная» версия:
public class Options {
private String option1;
private int option2;
// ...other options here
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private final Options options;
public Builder() {
this.options = new Options();
}
public Builder option1(String option1) {
this.options.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.options.option2 = option2;
return this;
}
public Options build() {
return options;//new RequestContext(this);
}
}
private Options() {
}
public static void main(String[] args) {
Options optionsVariation1 = new Options.Builder().option1("firefox").option2(1).build();
Options optionsVariation2 = new Options.Builder().option1("chrome").option2(2).build();
}
}
Как вы можете видеть вмоя "улучшенная версия", есть на 2 места меньше, в которые нам нужно добавить код о любых дополнительных свойствах (или опциях, в данном случае)!Единственный минус, который я вижу, это то, что переменные экземпляра внешнего класса не могут быть окончательными.Но класс по-прежнему неизменен без этого.
Есть ли какой-либо недостаток в этом улучшении ремонтопригодности?Должна быть причина, по которой он повторил свойства внутри вложенного класса, которые я не вижу?
PS: Не уверен, подходит ли этот тип вопроса для StackOverflow или относится к чему-то более субъективному, как [programmers.stackexchange.com], поэтому я заранее извиняюсь!
РЕДАКТИРОВАТЬ 1:
@ irreputable - Что-то подобное в Java?Я до сих пор не понимаю, как это становится потокобезопасным из-за изменений.Мне нужно изучить безопасную публикацию, как вы предлагаете.
public class OptionsDelegate {
private final OptionsData data;
private static class OptionsData {
String option1;
int option2;
}
// ...other options here
public String getOption1() {
return data.option1;
}
public int getOption2() {
return data.option2;
}
public static class Builder {
private OptionsData data;
public Builder() {
this.data = new OptionsData();
}
public Builder option1(String option1) {
this.data.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.data.option2 = option2;
return this;
}
public OptionsDelegate build() {
OptionsDelegate optionsDelegate = new OptionsDelegate(this.data);
this.data = null;
return optionsDelegate;
}
}
private OptionsDelegate(OptionsData data) {
this.data = data;
}
public static void main(String[] args) {
OptionsDelegate optionsVariation1 = new OptionsDelegate.Builder().option1("firefox").option2(1).build();
OptionsDelegate optionsVariation2 = new OptionsDelegate.Builder().option1("chrome").option2(2).build();
}
}