This article explains the Decorator design pattern, a structural pattern that allows dynamic addition of responsibilities to objects without modifying their core structure. It's crucial for achieving flexible and modular systems by promoting composition over inheritance and adhering to the Open/Closed Principle.
Read original on Dev.to #architectureThe Decorator pattern, a key GoF (Gang of Four) structural design pattern, addresses the challenge of extending object functionality dynamically without incurring a
The Decorator pattern enables adding new behaviors to individual objects at runtime in a transparent manner. Instead of rigid inheritance hierarchies, which can lead to a 'subclass explosion' when combining multiple features, the Decorator *wraps* the original object with additional layers of behavior. Each wrapper (decorator) adds a specific responsibility, effectively composing functionalities without altering the decorated object's internal structure. This results in a system that is significantly more flexible and modular.
When to Use Decorator
Consider the Decorator pattern when you need to dynamically add responsibilities to objects without altering their source code, when seeking to avoid excessive subclass creation, or when looking for a flexible alternative to inheritance for extending functionality.
The pattern involves four main elements: a Component interface (the contract), Concrete Components (the base objects), an abstract Decorator (which holds a reference to a Component and implements its interface), and Concrete Decorators (which add specific functionalities). The example in the article demonstrates this with a graphical component (Button) and a decorator adding a Red Border.
// Component
interface Component {
void draw();
}
// Concrete Component
class Button implements Component {
public void draw() {
System.out.println("Drawing a button");
}
}
// Decorator Abstract Class
abstract class BorderDecorator implements Component {
protected Component component;
public BorderDecorator(Component component) {
this.component = component;
}
public void draw() {
component.draw();
drawBorder();
}
protected abstract void drawBorder();
}
// Concrete Decorator
class RedBorderDecorator extends BorderDecorator {
public RedBorderDecorator(Component component) {
super(component);
}
protected void drawBorder() {
System.out.println("Drawing a red border");
}
}This pattern allows decorators to be