Шаблон декоратора на Java
1. обзор
A Decorator pattern can be used to attach additional responsibilities to an object either statically or dynamically. Декоратор предоставляет улучшенный интерфейс для исходного объекта.
В реализации этого шаблона мы предпочитаем составление наследованию - так что мы можем снова и снова сокращать накладные расходы на подклассы для каждого элемента декорирования. Рекурсия, связанная с этим дизайном, может использоваться для украшения нашего объекта столько раз, сколько нам нужно.
2. Пример шаблона декоратора
Предположим, у нас есть объект елки, и мы хотим его украсить. Украшение не меняет сам предмет; просто помимо новогодней елки мы добавляем некоторые предметы декора, такие как гирлянды, мишуру, верхушку дерева, пузырьковые огни и т. д .:
For this scenario, we’ll follow the original Gang of Four design and naming conventions. Сначала мы создадим интерфейсChristmasTree и его реализацию:
public interface ChristmasTree {
String decorate();
}
Реализация этого интерфейса будет выглядеть так:
public class ChristmasTreeImpl implements ChristmasTree {
@Override
public String decorate() {
return "Christmas tree";
}
}
Теперь мы создадим абстрактный классTreeDecorator для этого дерева. Этот декоратор будет реализовывать интерфейсChristmasTree, а также содержать тот же объект. Реализованный метод из того же интерфейса просто вызовет методdecorate() из нашего интерфейса:
public abstract class TreeDecorator implements ChristmasTree {
private ChristmasTree tree;
// standard constructors
@Override
public String decorate() {
return tree.decorate();
}
}
Теперь создадим какой-нибудь декоративный элемент. Эти декораторы расширят наш абстрактный классTreeDecorator и изменят его методdecorate() в соответствии с нашим требованием:
public class BubbleLights extends TreeDecorator {
public BubbleLights(ChristmasTree tree) {
super(tree);
}
public String decorate() {
return super.decorate() + decorateWithBubbleLights();
}
private String decorateWithBubbleLights() {
return " with Bubble Lights";
}
}
Для этого случая верно следующее:
@Test
public void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
assertEquals(tree1.decorate(),
"Christmas tree with Garland");
ChristmasTree tree2 = new BubbleLights(
new Garland(new Garland(new ChristmasTreeImpl())));
assertEquals(tree2.decorate(),
"Christmas tree with Garland with Garland with Bubble Lights");
}
Обратите внимание, что в первом объектеtree1 мы украшаем его только однимGarland, тогда как другой объектtree2 мы украшаем однимBubbleLights и двумяGarlandsс. Этот шаблон дает нам такую гибкость, чтобы добавлять столько декораторов, сколько мы хотим во время выполнения.
4. Заключение
В этой статье мы рассмотрели шаблон дизайна декоратора. Это хороший выбор в следующих случаях:
-
Когда мы хотим добавить, улучшить или даже удалить поведение или состояние объектов
-
Когда мы просто хотим изменить функциональность одного объекта класса и оставить другие без изменений
Полный исходный код этого примера доступенover on GitHub.