Подтвердить что ты не робот

Рисунок Builder против объекта конфигурации

Шаблон компоновщика популярен для создания неизменяемых объектов, но для создания строителя есть некоторые накладные расходы на программирование. Поэтому мне интересно, почему бы просто не использовать объект конфигурации.

Использование построителя будет выглядеть так:

Product p = Product.name("Vodka").alcohol(0.38).size(0.7).price(17.99).build();

Очевидно, что это очень читаемо и кратким, но вы должны реализовать построитель:

public class Product {

    public final String name;
    public final float alcohol;
    public final float size;
    public final float price;

    private Product(Builder builder) {
        this.name = builder.name;
        this.alcohol = builder.alcohol;
        this.size = builder.size;
        this.price = builder.price;
    }

    public static class Builder {

        private String name;
        private float alcohol;
        private float size;
        private float price;

        // mandatory
        public static Builder name(String name) {
            Builder b = new Builder();
            b.name = name;
            return b;
        }

        public Builder alcohol(float alcohol) {
            this.alcohol = alcohol;
            return.this;
        }

        public Builder size(float size) {
            this.size = size;
            return.this;
        }

        public Builder price(float price) {
            this.price = price;
            return.this;
        }

        public Product build() {
            return new Product(this);
        }

    }

}

Моя идея состоит в том, чтобы уменьшить код с помощью простого объекта конфигурации, подобного этому:

class ProductConfig {

        public String name;
        public float alcohol;
        public float size;
        public float price;

        // name is still mandatory
        public ProductConfig(String name) {
            this.name = name;
        }

}

public class Product {

    public final String name;
    public final float alcohol;
    public final float size;
    public final float price;

    public Product(ProductConfig config) {
        this.name = config.name;
        this.alcohol = config.alcohol;
        this.size = config.size;
        this.price = config.price;
    }

}

Использование:

ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);

Это использование требует еще нескольких строк, но также очень читаемо, но реализация намного проще и, возможно, его легче понять для тех, кто не знаком с шаблоном построителя. Кстати: есть ли название для этого шаблона?

Есть ли недостаток в подходе конфигурации, который я забыл?

4b9b3361

Ответ 1

Рисунок построителя улучшает развязку - ваш Продукт может быть интерфейсом, и единственный класс, который знает о реализации (или реализации, в некоторых случаях), является строителем. Если строитель также реализует интерфейс, вы можете ввести его в свой код, чтобы увеличить развязку.

Эта развязка означает, что ваш код более удобен в обслуживании и проще тестировать.

Ответ 2

Вы теряете несколько преимуществ шаблона построителя, как уже отмечалось (новое уродливое и сложнее поддерживать и утечка деталей по сравнению с чистым построителем).

Единственное, что я пропустил, однако, состоит в том, что шаблон построителя можно использовать для обеспечения так называемых "беглых интерфейсов".

Вместо этого:

ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);

Вы можете сделать:

ProductFactory.create()
    .drink("Vodka")
    .whereAlcohoolLevelIs(0.38)
    .inABottleSized(0.7)
    .pricedAt(17.99)
    .build();

Не все любят плавные интерфейсы, но они, безусловно, очень приятное использование шаблона построителя (все беглые интерфейсы должны использовать шаблон построителя, но не все шаблоны построителя - это плавные интерфейсы).

Некоторые отличные коллекции Java, такие как коллекции Google, делают очень либеральное и очень хорошее использование "плавных интерфейсов". Я бы выбрал их в любой день по сравнению с подходом "более простой и понятный персонаж":)

Ответ 3

Какую проблему вы пытаетесь решить с помощью своего шаблона? Шаблон построителя используется для объектов со многими (необязательными) параметрами, чтобы предотвратить тонны разных конструкторов или очень длинные. Он также сохраняет ваш объект в согласованном состоянии (по сравнению с javabean pattern) во время строительства.

Разница между построителем и "конфигурационным объектом" (выглядит как хорошее имя) заключается в том, что вам все равно нужно создать объект с теми же параметрами с помощью конструктора или getter/setter. Это а) не решает проблему конструктора или б) сохраняет объект конфигурации в несогласованном состоянии. Несогласованные состояния объекта config действительно не повредит его, но вы можете передать незавершенный объект конфигурации в качестве параметра. [Ссылка Michids на типы phantom, похоже, решает эту проблему, но это снова убивает читаемость (new Foo<TRUE,TRUE, TRUE, FALSE, TRUE> kinda sucks).] Это большое преимущество шаблона построителя: вы можете проверить свои параметры перед тем, как создать объект и вы можете вернуть любой подтип (действует как factory).

Конфигурационные объекты действительны для наборов параметров, которые являются обязательными. Я видел этот шаблон много раз в .NET или Java раньше.

Ответ 4

IMO, шаблон построителя гораздо более роботен, если у вас есть такие вещи, как проверка и т.д.

Шаблон строителя в вашем случае можно изменить, чтобы сделать следующее:

Product p = new ProductBuilder("pName").alcohol(0.38).size(0.7).price(17.99).build();

Метод build() может выполнять все материалы проверки, необходимые для вашего строителя. У шаблона строителя также есть несколько проектных авангардов (все из которых могут быть неприменимы в вашем случае). Для deatils проверьте question

Ответ 5

Рассматривали ли вы использование строитель-строитель?

Я думаю, что строитель (с префиксами типа "С" ) читает более натружно/плавно.

Ответ 6

Я лично считаю, что шаблон строителя с первого взгляда предлагает вам более чистый код, где эти объекты фактически используются. С другой стороны, отсутствие геттеров/сеттеров не будет очень полезно для многих фреймворков, которые ожидают геттеры/сеттеры для верблюда. Это серьезный откат, который я чувствую.

Что мне нравится с getters/seters, так это то, что вы четко видите, что делаете: получите или установите. Я чувствую себя со строителем, я теряю немного интуитивной ясности здесь.

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

Мой практический опыт в том, что я обычно лучше разбираюсь с геттерами/сеттерами и конструкторами. Это позволяет мне повторно использовать эти POJO для любых целей.

Хотя я вижу цель вашего объекта Config, я также думаю, что это еще больше накладных расходов, чем строитель, и для чего? Что не так с сеттерами?

Возможно, нам нужно придумать предложение WITH: Например, скажем, у вас есть

public Class FooBar() {
    private String foo;

    public void setFoo(String bar) { 
      this.foo = bar; 
    }

    public String getFoo() { 
        return this.foo; 
    }
}

public static void main(String []args) {

 FooBar fuBar = new FooBar();
 String myBar;

 with fuBar {
    setFoo("bar");
    myBar = getFoo(); 
 }
}

А я не знаю... Я думаю, что это может привести к более быстрому написанию кода без всяких внутренних проблем. Есть ли у кого-нибудь связь с гуру Oracle Java?

Это не выглядит так же чисто, как использование объекта с построителем, но вы сохраняете время построения строителя. И вы все равно можете использовать класс как регулярное pojo/ bean, которое можно использовать в рамках...

Вы, ребята, действительно хотели бы эту статью, или вы думаете, что это скорее сосать? Приветствия

Ответ 7

Шаблон конфигурации и шаблон построителя функционально эквивалентны. Они оба решают одни и те же проблемы -

  • Устранить необходимость в нескольких подписях конструктора

  • Разрешить поля только для установки

  • Разрешить потребителям устанавливать только те значения, которые им нужны, и иметь логические значения по умолчанию для других значений

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

Ответ 8

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

Вы используете простой объект value для хранения нескольких аргументов, которые нужны функции (/method/constructor), нет ничего плохого в этом, это было сделано целую вечность. Пока мы не называем необязательными параметрами, нам придется разрабатывать обходные пути, подобные этому, - это позор, а не какое-то чертовски блестящее изобретение богов на Солнце.

Реальная разница заключается в том, что вы открываете поля напрямую. У Джошуа никогда не было публичного изменчивого поля, но он пишет API, который будет использоваться миллионами людей, большинство из которых являются идиотами, и API должны быть в безопасности, чтобы развиваться на десятилетия вперед, и они могут выделять много человеко-месяцев только для разработки простой класс

Кому мы должны это надумать?

Ответ 9

Нельзя использовать общедоступное поле, но защищенное или закрытое. Для доступа вам следует использовать геттеры и сеттер, чтобы сохранить инкапсуляцию.