Должен ли Builder.build () возвращать состояние по умолчанию? - PullRequest
3 голосов
/ 31 мая 2019

При использовании шаблона Builder всегда возникает вопрос, имеют ли поля значение по умолчанию или нет? Я не могу найти надежный источник, где это четко определено ...

Проблема в удобочитаемости: что возвращает Car.Builder().build()? Мне всегда нужно проверять конкретную реализацию Builder, чтобы увидеть, какие значения по умолчанию используются. Разве нельзя использовать Builder для создания сложных объектов, которые по определению не имеют простого состояния по умолчанию?

Альтернативой может быть проверка того, установлены ли все обязательные поля внутри метода build():

fun build() : Car {
    return if (doors != null && hp != null) Car(doors, hp, color) // color can be null
    else throw IllegalArgumentException("Door count and HP is mandatory!")
}

... или это считается плохой практикой?

Ответы [ 2 ]

1 голос
/ 01 июня 2019

Вы не нашли общий ответ на свой вопрос, потому что его нет. Это зависит от контекста, в котором используется построитель, или от деталей объекта, который строит.

Иногда имеет смысл возвращать объект по умолчанию, где все его члены инициализируются значениями по умолчанию. Но тогда этот объект по умолчанию должен быть действительным. Например. для создания объекта регистратора было бы правильным вернуть регистратор, который регистрирует на консоли с форматированием по умолчанию и уровнем журнала по умолчанию. Кто-то может мгновенно использовать его.

Но иногда чистый объект по умолчанию не имеет смысла. Создание полностью настроенного HTTP-клиента по умолчанию не имеет смысла, поскольку он не будет обеспечивать минимальное ожидаемое поведение, поскольку целевой URL может быть чем-то неожиданным. В этом случае вы можете написать конструктор для класса построителя, который принимает URL-адрес в качестве параметра (может быть, также некоторый объект данных), а затем предварительно сконфигурировать объект клиента со значениями по умолчанию (например, заголовок запроса по умолчанию, время ожидания по умолчанию, размер буфера по умолчанию и т. Д.) , Этот объект будет соответствовать минимальным ожиданиям использования. Каждый последующий вызов установщика будет перезаписывать значение по умолчанию, где каждый установщик должен проверять правильность аргументов, прежде чем принимать их.

Но вы всегда должны, когда это возможно, пытаться использовать значения по умолчанию для исключений. Когда для создания объекта требуется обязательная информация, сделайте ее общедоступной, поместив ее в конструктор. Таким образом, вы можете быть уверены, что ваш объект всегда находится в допустимом и полезном состоянии. В случае построителя HTTP-клиента вы можете вызвать исключение, если URL-адрес искажен, чтобы дать разработчику подсказку, что его код, который создает URL-адрес, может иметь недостатки. Возможно, прочитайте Лучшие практики для исключений .

Имея в виду решение написать конструкторы для сбора всех необходимых параметров (для которых нельзя установить полезные значения по умолчанию), ваш метод build() finalize может и должен всегда и в любое время возвращать действительный и полезный объект. Это делает вашего строителя удобным. (В противном случае пользователь строителя будет вынужден прочитать документацию, чтобы узнать, какие сеттеры вызывать. Все знают, что вам не нравится писать документацию. Все знают, что вам не нравится прочитайте документацию перед использованием некоторых классов. Все чувствуют то же самое).

1 голос
/ 31 мая 2019

Я бы не помещал значения по умолчанию в класс Car, но вместо этого помещал бы значения по умолчанию для конкретных конструкторов.

class SedanBuilder {
    var doors = 4
    var wheels = 4
    var driver = null // we have to set driver

    ... setters ...
    fun build() {

        return Car(wheels, doors, driver)
    }
}

и другой строитель может использовать другие значения по умолчанию

class SchumachersCarBuilder {
    var doors = 4
    var wheels = 4
    var driver = Person("Michael")

    ... setters ...
    fun build() {

        return Car(wheels, doors, driver)
    }
}

И, конечно же, вы должны проверить все обязательные параметры внутри Car конструктор

...