Является ли этот Monster Builder хорошим шаблоном Builder/Factory для абстрагирования длинных конструкторов, смешанных сJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Является ли этот Monster Builder хорошим шаблоном Builder/Factory для абстрагирования длинных конструкторов, смешанных с

Сообщение Anonymous »

Это вопрос человеческого интерфейса об объединении шаблона построителя шагов с шаблонами расширенного построителя или мастера-построителя в творческий DSL. Он использует плавный интерфейс, хотя использует цепочку методов, а не каскадирование. То есть методы возвращают разные типы.
Я сталкиваюсь с классом-монстром, имеющим два конструктора, которые принимают смесь целых чисел, строк и массива строк. Каждый конструктор имеет длину 10 параметров. Он также имеет около 40 дополнительных сеттеров; некоторые из них конфликтуют друг с другом, если используются вместе. Его код построения выглядит примерно так:

Код: Выделить всё

Person person = Person("Homer","Jay", "Simpson","Homie", null, "black", "brown",
new Date(1), 3, "Homer Thompson", "Pie Man", "Max Power", "El Homo",
"Thad Supersperm", "Bald Mommy", "Rock Strongo", "Lance Uppercut", "Mr. Plow");

person.setClothing("Pants!!");
person.setFavoriteBeer("Duff");
person.setJobTitle("Safety Inspector");
В конечном итоге это не удается, потому что оказывается, что установка любимого пива и должности несовместима. Эх.
Редизайн класса монстров невозможен. Он широко используется. Оно работает. Я просто больше не хочу смотреть, как его строят напрямую. Я хочу написать что-нибудь чистое, что будет его кормить. Что-то, что будет следовать своим правилам, не заставляя разработчиков их запоминать.
В отличие от замечательных шаблонов построения, которые я изучал, эта штука не делится на разновидности или категории. Некоторые поля требуются постоянно, другие — при необходимости, а некоторые — только в зависимости от того, что было установлено ранее. Конструкторы не телескопические. Они предоставляют два альтернативных способа перевести класс в одно и то же состояние. Они длинные и некрасивые. То, что они хотят, зависит от них.
Свободный строитель определенно облегчит просмотр длинных конструкторов. Однако огромное количество дополнительных сеттеров загромождает необходимые. И есть требование, которому не удовлетворяет каскадный построитель Fluent: принудительное соблюдение времени компиляции.
Конструкторы заставляют разработчика явно добавлять обязательные поля, даже если они обнуляются. Это теряется при использовании каскадного построителя Fluent. Точно так же, как это теряется с сеттерами. Мне нужен способ удержать разработчика от сборки до тех пор, пока не будут добавлены все необходимые поля.
В отличие от многих шаблонов компоновщика, мне нужна не неизменяемость. Я выхожу из класса таким, каким его нашел. Я хочу знать, что построенный объект находится в хорошем состоянии, просто взглянув на код, который его создает. Без обращения к документации. Это означает, что программисту необходимо выполнить условно необходимые шаги.

Код: Выделить всё

Person makeHomer(PersonBuilder personBuilder){ //Injection avoids hardcoding implementation
return personBuilder

// -- These have good default values, may be skipped, and don't conflict -- //
.doOptional()
.addClothing("Pants!!")   //Could also call addTattoo() and 36 others

// -- All fields that always must be set.  @NotNull might be handy. -- //
.doRequired()                 //Forced to call the following in order
.addFirstName("Homer")
.addMiddleName("Jay")
.addLastName("Simpson")
.addNickName("Homie")
.addMaidenName(null)      //Forced to explicitly set null, a good thing
.addEyeColor("black")
.addHairColor("brown")
.addDateOfBirth(new Date(1))
.addAliases(
"Homer Thompson",
"Pie Man",
"Max Power",
"El Homo",
"Thad Supersperm",
"Bald Mommy",
"Rock Strongo",
"Lance Uppercut",
"Mr. Plow")

// -- Controls alternatives for setters and the choice of constructors -- //
.doAlternatives()           //Either x or y. a, b, or c.  etc.
.addBeersToday(3)       //Now can't call addHowDrunk("Hammered");
.addFavoriteBeer("Duff")//Now can’t call addJobTitle("Safety Inspector");

.doBuild()                  //Not available until now
;
}
Person может быть создан после addBeersToday(), поскольку в этот момент вся информация о конструкторе известна, но не возвращается до тех пор, пока не будет сделана функция doBuild().

Код: Выделить всё

public Person(String firstName, String middleName, String lastName,
String nickName, String maidenName, String eyeColor,
String hairColor, Date dateOfBirth, int beersToday,
String[] aliases);

public Person(String firstName, String middleName, String lastName,
String nickName, String maidenName, String eyeColor,
String hairColor, Date dateOfBirth, String howDrunk,
String[] aliases);
Эти параметры устанавливают поля, которые никогда не должны оставлять значения по умолчанию. beersToday и HowDrunk задают одно и то же поле разными способами. FavoriteBeer и jobTitle — это разные поля, но они вызывают конфликты с тем, как используется класс, поэтому следует задать только одно. Они обрабатываются с помощью установщиков, а не конструкторов.
Метод doBuild() возвращает объект Person. Это единственный тип, который это делает, и Person — единственный тип, который он возвращает. При этом Person полностью инициализируется.
На каждом этапе интерфейса возвращаемый тип не всегда один и тот же. Изменение типа — это то, как разработчик руководствуется этими шагами. Он предлагает только действительные методы. Метод doBuild() недоступен до тех пор, пока не будут выполнены все необходимые шаги.

Префиксы do/add — это загадка для написания проще, потому что изменяющийся тип возвращаемого значения
не соответствует назначению и приводит к тому, что рекомендации intelisense становятся алфавитными
в eclipse. Я подтвердил, что у intellij нет этой проблемы. Спасибо, NimChimpsky.

Этот вопрос касается интерфейса, поэтому я приму ответы, которые не обеспечивают реализацию. Но если вы знаете такой, поделитесь.
Если вы предлагаете альтернативный шаблон, покажите, какой интерфейс используется. Используйте все входные данные из примера.
Если вы предлагаете использовать представленный здесь интерфейс или его небольшую вариацию, защитите его от подобной критики.
Что мне действительно хочется знать, так это то, предпочтут ли большинство людей использовать для сборки этот интерфейс или какой-то другой. Это вопрос человеческого интерфейса. Нарушает ли это PoLA? Не беспокойтесь о том, насколько сложно это будет реализовать.
Однако, если вам интересно узнать о реализации:
Неудачная попытка (не у меня недостаточно состояний или понимание действительных и не установленных по умолчанию)
Реализация построителя шагов (недостаточно гибкая для нескольких конструкторов или альтернатив)
Усовершенствованный построитель (Все еще лайнер, но имеет гибкие состояния)
Мастер создания (создает разветвление, но не запоминает путь для выбора конструктора)

Требование:
  • Класс монстров (человек) уже закрыт для модификации и расширения; без обид
Цели:
  • Скрыть длинные конструкторы, поскольку класс монстров 10 обязательных параметров.
  • Определите, какой конструктор вызывать на основе используемых альтернатив.
  • Запретить конфликтующие методы установки.
  • Применять правила. во время компиляции
Намерение:
  • Четко сигнализировать, когда значения по умолчанию неприемлемы.


Подробнее здесь: https://stackoverflow.com/questions/229 ... ng-long-co
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»