Python
Decorator
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() + 2
The 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 = 13
This is an alternative to subclassing; you create many combinations without increasing the number of classes.
Exercise 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()).
Show example 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())
Test yourself
-
Complete the Decorator __init__ body
class MilkDecorator:
def __init__(self, coffee):
self.____ = coffee
Show answer
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
-
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
Show answer
Inner object's cost + 2 — self._coffee.cost() + 2 calls the inner and adds.
-
Match the Decorator concepts
- MilkDecorator
- Is the wrapper
- self._coffee
- Is the inner object
- cost() + 2
- Adds behavior
- layering
- Dynamic extension
Next lesson: Summary - Design patterns