terminal

codeando_simple

terminal

menu

terminal

search_module

guest@codeandosimple: ~/system/search $ grep -r "" .

Press [ENTER] to execute search

Status

Engine: Ready

Database: Online

Index: V2.1.0_LATEST

bash -- cat decorator.md
guest@codeandosimple: ~/blog/design-patterns $ cat decorator.md

Decorator Pattern_

// "The only impossible journey is the one you never begin" - Jean-Paul Sartre

# Purpose

The Decorator pattern allows adding additional responsibilities to an object dynamically, at runtime, without altering the structure of existing classes.

It is especially useful for extending functionalities in a flexible and reusable way.

# Problem

The need to extend the functionality of a class dynamically, without resorting to inheritance, which generates a rigid and less flexible hierarchy.

# Solution

The solution proposed by the Decorator is to wrap the original object in a "decorator" object, which adds the desired functionality.

  • Object Decoration: Extends functionality by wrapping them with decorator classes.

  • Flexible Combination: Allows combining additional functionalities flexibly by using multiple decorators.

# Structure

Decorator UML Structure

# Participants

  • Component: Interface for objects to which responsibilities are to be added.
  • ConcreteComponent: Object to be decorated.
  • Decorator: Abstract class that wraps a Component object.
  • ConcreteDecorator: Adds functionality to the Component.

# When to Use It

  • Add responsibilities dynamically and transparently.

  • When extension by subclassing is impractical.

# Advantages

  • verified

    More Flexibility: Dynamic responsibilities.

  • verified

    Avoids overloaded classes: Separates optional functionalities.

  • verified

    Combination and Reusability: Easy mixing of behaviors.

# Disadvantages

  • warning

    Complexity: Multiple small layers.

  • warning

    Configuration: Hard to configure with many layers.

  • warning

    Identification: Hard to see the base object.

# Example: Customizable Coffee Shop

We are developing a system that needs to offer a large variety of customizable coffees (milk, sugar, cream, etc.).

Problem

Create a class for each combination would generate an explosion of classes hard to maintain.

Proposed solution

We use Decorator to dynamically add ingredients to the base coffee. Each decorator adds its own cost and description.

Coffee Decorator Example

# Java Code

interface Coffee {
    double getCost();
    String getDescription();
}

class SimpleCoffee implements Coffee {
    public double getCost() { return 2.0; }
    public String getDescription() { return "Simple coffee"; }
}

abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    public CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; }
    public double getCost() { return decoratedCoffee.getCost(); }
    public String getDescription() { return decoratedCoffee.getDescription(); }
}

class WithMilk extends CoffeeDecorator {
    public WithMilk(Coffee coffee) { super(coffee); }
    public double getCost() { return super.getCost() + 0.5; }
    public String getDescription() { return super.getDescription() + ", with milk"; }
}

public class Client {
    public static void main(String[] args) {
        Coffee myCoffee = new SimpleCoffee();
        myCoffee = new WithMilk(myCoffee);
        myCoffee = new WithSugar(myCoffee);
        System.out.println("Cost: " + myCoffee.getCost());
    }
}

# Mapping Participants

  • Coffee (Component): Common interface.
  • SimpleCoffee (ConcreteComponent): Base component.
  • CoffeeDecorator (Decorator): Base class for decorators.
  • WithMilk, WithSugar (ConcreteDecorators): Functionality aggregators.
  • Client: Assembles coffees with ingredients.

# Conclusions

The Decorator pattern gives a flexible and scalable solution, making it easy to add new ingredients in the future without modifying existing code.

# Related Patterns

Strategy

Decorator changes the skin; Strategy changes the guts of an object.

Composite

Decorator can be viewed as a degenerate Composite with only one component.

Adapter

Decorator changes responsibilities; Adapter changes the interface.