Паттерн проектирования «Декоратор» / «Decorator»
Паттерн декоратор (Decorator) – один из наиболее известных и распространенных паттернов проектирования, используемых в Java. Он позволяет динамически добавлять новую функциональность к объектам, не изменяя их исходный код. Это очень удобно, когда нужно добавить дополнительные возможности к уже существующему объекту.
Пример использования паттерна декоратор в Java: Предположим, у нас есть интерфейс Pizza, который имеет методы getDescription() и getCost(). Этот интерфейс представляет собой базовый класс для разных типов пиццы.
public interface Pizza {
String getDescription();
double getCost();
}
Теперь мы хотим добавить новые возможности к объекту Pizza, не меняя его исходный код. Для этого мы создадим класс-декоратор PizzaDecorator, который также реализует интерфейс Pizza.
public abstract class PizzaDecorator implements Pizza {
protected Pizza pizza;
public PizzaDecorator(Pizza pizza) {
this.pizza = pizza;
}
}
Класс PizzaDecorator имеет ссылку на объект pizza, который он декорирует. Он также реализует методы интерфейса Pizza.
Теперь мы можем создать конкретные декораторы, которые будут добавлять новые возможности к объекту Pizza. Например, мы можем создать декоратор CheeseDecorator, который будет добавлять сыр к пицце.
public class CheeseDecorator extends PizzaDecorator {
public CheeseDecorator(Pizza pizza) {
super(pizza);
}
public String getDescription() {
return pizza.getDescription() + ", Cheese";
}
public double getCost() {
return pizza.getCost() + 2.00;
}
}
Декоратор CheeseDecorator добавляет сыр к пицце. Он также имеет ссылку на объект pizza, который он декорирует, и реализует методы интерфейса Pizza.
Теперь мы можем создать объекты Pizza и добавлять к ним декораторы. Например, мы можем создать объект PepperoniPizza и добавить к нему декоратор CheeseDecorator.
Pizza pepperoniPizza = new PepperoniPizza();
pepperoniPizza = new CheeseDecorator(pepperoniPizza);
System.out.println(pepperoniPizza.getDescription() + ": $" + pepperoniPizza.getCost());
В этом примере мы создали объект PepperoniPizza, а затем добавили к нему декоратор CheeseDecorator. Мы также вывели на консоль описание пиццы и ее стоимость.
Вывод на консоль будет следующим: Pepperoni, Cheese: $12.00
Этот пример демонстрирует,
как паттерн декоратор может быть использован для добавления новой функциональности к существующим объектам, не изменяя их исходный код. Таким образом, мы можем создавать более гибкие и модульные приложения, которые легче поддерживать и расширять.
Помимо добавления новых возможностей, паттерн декоратор также может быть использован для убирания возможностей. Например, мы можем создать декоратор NoCheeseDecorator, который будет убирать сыр с пиццы.
public class NoCheeseDecorator extends PizzaDecorator {
public NoCheeseDecorator(Pizza pizza) {
super(pizza);
}
public String getDescription() {
return pizza.getDescription().replace(", Cheese", "");
}
public double getCost() {
return pizza.getCost() - 2.00;
}
}
Этот декоратор убирает сыр с пиццы. Он также имеет ссылку на объект pizza, который он декорирует, и реализует методы интерфейса Pizza.
Теперь мы можем создать объект PepperoniPizza и добавить к нему декораторы CheeseDecorator и NoCheeseDecorator.
Pizza pepperoniPizza = new PepperoniPizza();
pepperoniPizza = new CheeseDecorator(pepperoniPizza);
pepperoniPizza = new NoCheeseDecorator(pepperoniPizza);
System.out.println(pepperoniPizza.getDescription() + ": $" + pepperoniPizza.getCost());
В этом примере мы создали объект PepperoniPizza, а затем добавили к нему декоратор CheeseDecorator и NoCheeseDecorator. Мы также вывели на консоль описание пиццы и ее стоимость.
Вывод на консоль будет следующим: Pepperoni: $10.00
Этот пример демонстрирует, как паттерн декоратор может быть использован для убирания возможностей объекта.
В заключение, паттерн декоратор – это очень мощный инструмент для добавления новых возможностей к объектам и убирания ненужных возможностей. Он позволяет создавать более гибкие и модульные приложения, которые легче поддерживать и расширять. Кроме того, паттерн декоратор является одним из основных паттернов проектирования, используемых в Java, и важен для понимания любого Java-разработчика.