Decorator
- Java course
- Advanced
- Lesson 41/82
- 5 min
Learn the Decorator pattern.
The Decorator pattern
The Decorator adds behavior by wrapping an object. The wrapping class implements the same interface as the wrapped object, so the client sees no difference. Several decorators can nest.
Example: a Coffee interface, a SimpleCoffee base object. A MilkDecorator takes a Coffee inside and adds the milk price to its cost. new MilkDecorator(new SimpleCoffee()) gives a wrapped coffee. Wrapping is preferred over inheritance, so behavior can be added at runtime.
Nested decorators
Decorators can nest: new SugarDecorator(new MilkDecorator(new SimpleCoffee())). Each layer adds its own contribution; the result is the sum of all layers' costs.
This prevents the inheritance hierarchy from bloating. Instead of a new subclass for each feature, an independent decorator is written. The client customizes the object by picking the layers it wants. This flexibility is common in IO streams (for example BufferedReader).
Practice Add a milk decorator to coffee
Define a Coffee interface with int cost(). A SimpleCoffee class implements it and cost returns 10. A MilkDecorator class implements the Coffee interface; its constructor takes a Coffee inner, and cost returns inner.cost() + 3. In main, wrap with new MilkDecorator(new SimpleCoffee()) and print the cost() result with System.out.println.
Starter code
// Define the Coffee interface and SimpleCoffee class
// Wrap with MilkDecorator
// Print the total cost in mainSample solution
interface Coffee { int cost(); }
class SimpleCoffee implements Coffee {
public int cost() { return 10; }
}
class MilkDecorator implements Coffee {
private Coffee inner;
public MilkDecorator(Coffee inner) { this.inner = inner; }
public int cost() { return inner.cost() + 3; }
}
public class DecoratorDemo {
public static void main(String[] args) {
Coffee c = new MilkDecorator(new SimpleCoffee());
System.out.println(c.cost());
}
}Expected output
13
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does a Decorator share with the object it wraps?
- The same interface Correct answer
- The fields
- The constructor
- The static state
Explanation: A Decorator implements the same interface as the wrapped object.
2 Match the Decorator concepts
| Term | Meaning |
|---|---|
Coffee |
Common interface |
SimpleCoffee |
Base object |
MilkDecorator |
Wrapper |
inner.cost() |
Delegate to inner |
3 Complete the Decorator constructor
public MilkDecorator(____ inner) { this.inner = inner; }
public MilkDecorator(Coffee inner) { this.inner = inner; }
Explanation: The Decorator takes the wrapped type.