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

Builder Vs Decorator pattern

Из Когда вы будете использовать шаблон Builder?,

Говорят, что шаблон компоновщика подходит для примера Pizza.

Почему не Decorator? путем обработки Сыра, Пепперони, Бэкона в качестве дополнительных украшений на базовой пицце.

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

Прояснить Pls. Я также ищу хороший реальный образец декоратора и причину, почему он подходит для этого конкретного примера. Спасибо.

4b9b3361

Ответ 1

Из статьи с рисунком декоратора wikipedia:

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

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

Другими словами, шаблон Builder позволяет легко построить объект, который расширяется в независимых направлениях во время построения, в то время как шаблон Decorator позволяет добавлять расширения к функциональности объекту после времени построения. Использование шаблона декоратора для построения объектов является плохим, потому что оно оставляет объект в несогласованном (или, по крайней мере, некорректном) состоянии до тех пор, пока не будут созданы все необходимые декораторы - аналогично проблеме JavaBean, использующей сеттеры для указания необязательных аргументов конструктора.

Ответ 2

Вы смешиваете две разные вещи. GoF классифицирует Builder как шаблон создания, а Decorator - структурный шаблон. Они описываются следующим образом (Gamma et al, стр. 1):

Builder (97) Отделить построение сложного объекта от его представления, чтобы тот же процесс построения мог создавать разные представления.

Decorator (175) Прилагайте дополнительные обязанности к объекту динамически. Декораторы обеспечивают гибкую альтернативу подклассу для расширения функциональности.

Обратите внимание на акцент на декораторе. Это гибкая альтернатива подклассу. Подклассификация используется для моделирования отношения is-a. Сыр - это не пицца. Пицца состоит из ряда ингредиентов, и это обычно моделируется с использованием композиции.

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

Чтобы принять реальный пример декоратора, я недавно хотел записать запросы, выполняемые с помощью jdbc в моем приложении java. Я выполнил это, выполнив класс LoggingConnection, который расширил интерфейс Connection.

public class LoggingConnection implements Connection
{
    public static class LogEntry
    {
        public String sql;
        public int invocationCount;
        public double avgTime;
        public double maxTime;
    }

    private Connection delegate;

    private Map<String, LogEntry> log;

    public LoggingConnection(Connection delegate)
    {
        this.delegate = delegate;
        this.log = new HashMap<String, LogEntry>();
    }

    public Map<String, LogEntry> getLog()
    {
        return log;
    }

    @Override
    public void clearWarnings()
    throws SQLException
    {
        delegate.clearWarnings();
    }

    @Override
    public void close()
    throws SQLException
    {
        delegate.close();
    }

    // forwarding declarations to all other methods declared in the interface
    ...
}

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

Connection conn = DriverManger.getConnection(dsn);

Объект conn в этом случае представляет собой реализацию, содержащуюся в драйвере, который я, как правило, не знаю имени. Представление подхода декоратора заключается в том, что я не должен знать и что он не привязан к конкретной реализации.

Ответ 3

Давайте рассмотрим ключевые характеристики Builder и Decorator.

Builder: (шаблон создания)

  • Слишком много аргументов для перехода от клиентской программы к классу Factory, который может быть подвержен ошибкам
  • Некоторые параметры могут быть необязательными в отличие от Factory, которые вынуждают отправлять все параметры
  • Объект тяжелый, его создание сложное. например создание различных видов пиццы

Decorator: (Структурный рисунок)

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

Когда использовать Decorator:

  • Обязанности и поведение объекта должны динамически добавляться/удаляться
  • Конкретные реализации должны быть отделены от обязанностей и поведения
  • Когда подклассификация слишком дорогостоящая, чтобы динамически добавлять/удалять обязанности

Возвращаясь к вашему запросу:

Builder - это правильный шаблон создания для Pizza. Сначала пицца создается с обязательными ингредиентами (Хлеб и т.д.). Сыр, Пепперони, Бэкон являются необязательными ингредиентами, но все же они могут быть частью пиццы во время процесса сборки.

Декоратор полезен для добавления динамических обязанностей во время выполнения для уже созданного объекта.

например.:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));

Подробнее см. ниже:

Сохранение строителя в отдельном классе (свободный интерфейс)

Когда использовать шаблон декоратора?

Ответ 4

Рисунок построителя специально используется для сборки и Decorator для добавления специальных функций post build. например, в приведенном выше примере Pizza мы можем решить использовать один из двух шаблонов на основе проблемного домена.

Если Chilli Flakes необходимы для пиццы, и у нас есть много ингредиентов, чтобы добавить к Pizza, из которых немногие из них элементарны, чтобы сделать Pizza съедобным (значимым состоянием), мы можем предпочесть использовать Builder. Как только Пицца будет построена, мы можем позже пойти и украсить ее различными начинками, такими как томатный соус, маслины и т.д.

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