Рубрики
Без рубрики

Шаблон декоратора в Java

Руководство по шаблону дизайна декоратора и его реализации на Java

Автор оригинала: baeldung.

1. Обзор

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

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

2. Пример шаблона декоратора

Предположим, у нас есть объект рождественской елки, и мы хотим его украсить. Украшение не меняет сам объект; просто в дополнение к рождественской елке мы добавляем некоторые элементы декора, такие как гирлянда, мишура, верхушка дерева, пузырьковые огни и т. Д.:

Для этого сценария мы будем следовать оригинальной группе из четырех соглашений о дизайне и именовании. Во-первых, мы создадим Рождественскую елку интерфейс и его реализацию:

public interface ChristmasTree {
    String decorate();
}

Реализация этого интерфейса будет выглядеть следующим образом:

public class ChristmasTreeImpl implements ChristmasTree {

    @Override
    public String decorate() {
        return "Christmas tree";
    }
}

Теперь мы создадим абстрактный Декоратор дерева класс для этого дерева. Этот декоратор будет реализовывать интерфейс Рождественская елка , а также удерживать один и тот же объект. Реализованный метод из того же интерфейса просто вызовет метод decorate() из нашего интерфейса:

public abstract class TreeDecorator implements ChristmasTree {
    private ChristmasTree tree;
    
    // standard constructors
    @Override
    public String decorate() {
        return tree.decorate();
    }
}

Теперь мы создадим какой-нибудь декоративный элемент. Эти декораторы расширят наш класс абстрактного Декоратора деревьев и изменят его метод 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");
}

Обратите внимание, что в первом объекте tree 1 мы украшаем его только одной гирляндой , в то время как другой объект tree2 мы украшаем одним BubbleLights и двумя Гирляндами . Этот шаблон дает нам возможность добавлять столько декораторов, сколько мы хотим во время выполнения.

4. Заключение

В этой статье мы рассмотрели шаблон дизайна декоратора. Это хороший выбор в следующих случаях:

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

Полный исходный код для этого примера доступен на GitHub .