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




В некоторых языках (например, Ruby или JavaScript) вы можете просто добавить новые функции в экземпляр A. Я заметил, что ваш вопрос помечен как Java, поэтому я предполагаю, что вы спрашиваете, почему вы не можете сделать это на Java. Причина в том, что Java статически типизирована. Экземпляр A может иметь только те методы, которые класс A определяет или наследует. Следовательно, если вы хотите во время выполнения предоставить экземпляру A метод, который A не определяет, тогда этот новый метод должен быть определен в другом классе.
Шаблон декоратора используется для динамического добавления возможностей к объектам (то есть во время выполнения). Обычно возможности объекта фиксируются при написании класса. Но важным моментом является то, что функциональность объекта расширяется таким образом, чтобы он был прозрачен для клиента объекта, поскольку он реализует тот же интерфейс, что и исходный объект, делегирующий ответственность декорированному объекту.
Шаблон декоратора работает в сценариях, где есть много дополнительных функций, которые может иметь объект. Без шаблона декоратора вам придется создавать разные классы для каждой конфигурации параметров объекта. Один очень полезный пример взят из книги Шаблоны проектирования Head First О'Рейли. Он использует пример кофейни, который звучит так же, как StarBucks.
Итак, у вас есть базовый кофе с таким методом, как стоимость.
public double cost(){
return 3.45;
}
Затем клиент может добавить сливки, которые стоят 0,35, поэтому теперь вы создаете класс CoffeeCream с методом стоимости:
public double cost(){
return 3.80;
}
Затем покупатель может захотеть мокко по цене 0,5, и он может захотеть мокко со сливками или мокко без сливок. Итак, вы создаете классы CoffeeMochaCream и CoffeeMocha. Затем клиент хочет двойные сливки, поэтому вы создаете класс CoffeeCreamCream… и т. д. В результате вы получаете взрыв класса. Прошу прощения за использованный плохой пример. Это немного поздно, и я знаю, что это тривиально, но это выражает суть.
Вместо этого вы можете создать абстрактный класс Item с помощью абстрактного метода стоимости:
public abstract class Item{
public abstract double cost();
}
И вы можете создать конкретный класс Coffee, расширяющий Item:
public class Coffee extends Item{
public double cost(){
return 3.45;
}
}
Затем вы создаете CoffeeDecorator, расширяющий тот же интерфейс и содержащий элемент.
public abstract class CoffeeDecorator extends Item{
private Item item;
...
}
Затем вы можете создать конкретные декораторы для каждого варианта:
public class Mocha extends CoffeeDecorator{
public double cost(){
return item.cost() + 0.5;
}
}
Обратите внимание, как декоратору все равно, какой тип объекта он оборачивает, пока он является Item? Он использует cost () объекта item и просто добавляет свою стоимость.
public class Cream extends CoffeeDecorator{
public double cost(){
return item.cost() + 0.35;
}
}
Теперь это возможно для большого количества конфигураций с этими несколькими классами: например
Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream
или же
Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream
И так далее.
@dhiller Ага. Шаблоны дизайна были первым, что я попробовал, и начал рекомендовать их всем своим студентам.
Этот пример легче понять, хотя я не думаю, что это правильная проблема, которую следует решать с помощью этого шаблона.
Кстати, если вы только начинаете работать с шаблонами, книга «Head First Design Patterns» - феноменальный. Это действительно упрощает понимание концепций и позволяет противопоставлять и сравнивать похожие шаблоны таким образом, чтобы их было до смешного легко понять.
Я должен поддержать это, книга невероятная. Фактически, приведенный выше пример кофе взят из этой книги, но в книге этот пример идет намного дальше.
Я нашел этот ответ более легким для понимания, чем статью в Википедии.