Decorator Pattern
Introduction
The Decorator Pattern is a structural design pattern that enables behavior to be added to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class.
Note: The Decorator Pattern is a flexible alternative to subclassing for extending functionality.
Key Concepts
- Component: An interface or abstract class defining the operations that can be dynamically added to concrete components.
- Concrete Component: The original object to which additional responsibilities can be attached.
- Decorator: A class that implements the same interface as the component and has a reference to a component object. It can add behavior to the component.
Implementation
Here's a step-by-step implementation of the Decorator Pattern in Python.
class Coffee:
def cost(self):
return 5
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 1
class SugarDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 0.5
# Usage
coffee = Coffee()
print("Cost of plain coffee: $", coffee.cost())
milk_coffee = MilkDecorator(coffee)
print("Cost of coffee with milk: $", milk_coffee.cost())
sugar_milk_coffee = SugarDecorator(milk_coffee)
print("Cost of coffee with milk and sugar: $", sugar_milk_coffee.cost())
Best Practices
- Favor composition over inheritance.
- Keep decorators focused on a single responsibility.
- Use decorators to adhere to the Open/Closed Principle (open for extension, closed for modification).
FAQ
What is the main advantage of the Decorator Pattern?
It allows you to add new functionalities to an object dynamically without altering its structure.
When should you use the Decorator Pattern?
Use it when you want to enhance the behavior of an object dynamically, and you want to keep the design flexible and reusable.