Урок 7.2. Декоратор (Decorator)
Шаблон проектирования "Декоратор" (Decorator) позволяет динамически добавлять новое поведение или функциональность объектам, не изменяя их структуру. Этот паттерн предоставляет гибкий способ расширения функциональности классов, позволяя комбинировать различные декораторы.
Пример использования паттерна Decorator на Java
Рассмотрим пример, в котором мы создадим систему для описания напитков. У нас будет базовый класс Beverage
, и мы будем использовать декораторы для добавления различных добавок, таких как молоко и сахар.
Шаг 1: Создание базового класса
public abstract class Beverage {
public abstract String getDescription();
public abstract double cost();
}
Шаг 2: Реализация конкретного напитка
public class Coffee extends Beverage {
@Override
public String getDescription() {
return "Coffee";
}
@Override
public double cost() {
return 2.00; // Цена кофе
}
}
Шаг 3: Создание абстрактного декоратора
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
Шаг 4: Реализация конкретных декораторов
public class Milk extends CondimentDecorator {
private Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double cost() {
return beverage.cost() + 0.50; // Добавляем стоимость молока
}
}
public class Sugar extends CondimentDecorator {
private Beverage beverage;
public Sugar(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Sugar";
}
@Override
public double cost() {
return beverage.cost() + 0.20; // Добавляем стоимость сахара
}
}
Шаг 5: Использование декоратора
Теперь мы можем использовать наш декоратор в коде:
public class DecoratorPatternDemo {
public static void main(String[] args) {
Beverage beverage = new Coffee();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
// Добавляем молоко
beverage = new Milk(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
// Добавляем сахар
beverage = new Sugar(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
}
}
Объяснение
-
Класс
Beverage
: Абстрактный класс, который определяет методыgetDescription()
иcost()
. Все напитки будут наследоваться от этого класса. -
Класс
Coffee
: Конкретная реализация напитка, которая возвращает описание и стоимость кофе. -
Класс
CondimentDecorator
: Абстрактный класс-декоратор, который также наследуется отBeverage
. Он переопределяет методgetDescription()
. -
Классы
Milk
иSugar
: Конкретные декораторы, которые добавляют функциональность к напиткам. Они принимают объектBeverage
и добавляют к его описанию и стоимости соответствующие добавки. -
Класс
DecoratorPatternDemo
: Демонстрирует использование декораторов. Мы создаем кофе, добавляем к нему молоко и сахар, и выводим итоговое описание и стоимость.
Заключение
Паттерн "Декоратор" позволяет динамически добавлять функциональность к объектам, не изменяя их структуру. Это делает код более гибким и расширяемым. В приведенном примере мы увидели, как можно использовать декораторы для добавления различных добавок к напиткам, сохраняя при этом чистоту и простоту основного кода.