Decorator
- Python course
- Advanced
- Lesson 65/83
- 5 min
Learn the Decorator pattern.
Decorator (design pattern)
The Decorator design pattern extends an object's behavior by wrapping it. It is different from Python's @decorator syntax; here a wrapper class holds the inner object and calls methods through it.
class Coffee:
def cost(self):
return 10
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 2The Decorator adds new behavior without changing the wrapped object; for example, milk, sugar and other add-ons are layered onto a drink.
Layered decorators
Decorators can be layered; each layer wraps the previous one. This allows adding behavior dynamically.
class SugarDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 1
c = SugarDecorator(MilkDecorator(Coffee()))
print(c.cost()) # 10 + 2 + 1 = 13This is an alternative to subclassing; you create many combinations without increasing the number of classes.
Practice Coffee cost with Decorator
Define class Coffee: with def cost(self): returning 10. Define class MilkDecorator: with def __init__(self, coffee): doing self._coffee = coffee. Method def cost(self): returns self._coffee.cost() + 2. Create c = MilkDecorator(Coffee()). Print the cost with print(c.cost()).
Starter code
# define Coffee class (cost = 10)
# define MilkDecorator class (store inner, cost + 2)
# wrap a Coffee instance with MilkDecorator
# print the costSample solution
class Coffee:
def cost(self):
return 10
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 2
c = MilkDecorator(Coffee())
print(c.cost())Expected output
12
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Complete the Decorator __init__ body
class MilkDecorator:
def __init__(self, coffee):
self.____ = coffee
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
Explanation: self._coffee = coffee stores the inner object.
2 What does MilkDecorator.cost() return in the Decorator pattern?
- It raises an error
- Just 2
- Just the inner object's cost
- Inner object's cost + 2 Correct answer
Explanation: self._coffee.cost() + 2 calls the inner and adds.
3 Match the Decorator concepts
| Term | Meaning |
|---|---|
MilkDecorator |
Is the wrapper |
self._coffee |
Is the inner object |
cost() + 2 |
Adds behavior |
layering |
Dynamic extension |