Ответ 1
Шаблон декоратора используется для динамического добавления возможностей объектов (то есть во время выполнения). Обычно объект будет иметь свои возможности, если вы напишете класс. Но важным моментом является то, что функциональность объекта расширяется таким образом, который прозрачен для клиента объекта, потому что он реализует тот же интерфейс, что и исходный объект делегирует ответственность за украшенный объект.
Шаблон декоратора работает в сценариях, где есть много дополнительных функций, которые могут иметь объекты. Без шаблона декоратора вам придется создать другой класс для каждой конфигурации объекта-опции. Один из примеров, который очень полезен, - это книга Head First Design Patterns книги О'Рейли. Он использует пример кафе, который звучит так же, как 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();
}
И вы можете создать конкретный класс кофе, который расширяет 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
И так далее.