Builder Vs Decorator pattern
Из Когда вы будете использовать шаблон Builder?,
Говорят, что шаблон компоновщика подходит для примера Pizza.
Почему не Decorator?
путем обработки Сыра, Пепперони, Бэкона в качестве дополнительных украшений на базовой пицце.
Это по той причине, что Сыр/Пепперони нужно строить отдельно. Я не думаю, что их нужно строить отдельно, поскольку они могут быть доступны для чтения.
Прояснить Pls.
Я также ищу хороший реальный образец декоратора и причину, почему он подходит для этого конкретного примера. Спасибо.
Ответы
Ответ 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.
Как только Пицца будет построена, мы можем позже пойти и украсить ее различными начинками, такими как томатный соус, маслины и т.д.
Кроме того, правильно указано, что они могут использоваться вместе, но это увеличит сложность. Поэтому мы должны использовать шаблоны с умом только тогда, когда это необходимо в проблемной области, иначе будет достаточно простой конструкции.