What is Decorator Pattern?
The Decorator Pattern is a structural design pattern that adds new behavior to an object dynamically without modifying its original code.
It wraps the original object and extends its functionality.
Why Use Decorator Pattern?
- Add features without changing existing code
- Follow Open/Closed Principle
- Avoid subclass explosion
- Enable flexible combinations of behaviors
Real-Time Scenario
In an Invoice System:
- Base amount = 1000
- Add discount
- Add tax
- Add logging
👉 Instead of modifying Invoice, we decorate it
Implementation
Step 1: Component Interface
public interface IInvoice
{
decimal GetAmount();
}
Step 2: Concrete Component
public class Invoice : IInvoice
{
public decimal GetAmount() => 1000;
}
Step 3: Decorator (Add Behavior)
public class DiscountDecorator : IInvoice
{
private readonly IInvoice _invoice;
public DiscountDecorator(IInvoice invoice)
{
_invoice = invoice;
}
public decimal GetAmount()
{
return _invoice.GetAmount() - 100;
}
}
Usage Example
IInvoice invoice = new Invoice();
// Add discount
invoice = new DiscountDecorator(invoice);
Console.WriteLine(invoice.GetAmount()); // 900
Multiple Decorators (Advanced)
Tax Decorator
public class TaxDecorator : IInvoice
{
private readonly IInvoice _invoice;
public TaxDecorator(IInvoice invoice)
{
_invoice = invoice;
}
public decimal GetAmount()
{
return _invoice.GetAmount() * 1.18m;
}
}
Usage with Multiple Layers
IInvoice invoice = new Invoice();
// Apply discount first
invoice = new DiscountDecorator(invoice);
// Then apply tax
invoice = new TaxDecorator(invoice);
Console.WriteLine(invoice.GetAmount());
👉 Behaviors are stacked dynamically
Key Concept
Instead of:
class InvoiceWithDiscountAndTax : Invoice { }
We do:
new TaxDecorator(new DiscountDecorator(new Invoice()));
👉 Flexible composition over inheritance
Advantages
- Add behavior without modifying original class
- Flexible and dynamic feature addition
- Avoids large inheritance hierarchies
- Promotes reusable components
Disadvantages
- Many small classes
- Harder to debug layered objects
- Can increase complexity
When to Use
- When you need to add features dynamically
- When modifying existing class is not allowed
- When multiple combinations of features are required
- When avoiding inheritance complexity
Real Project Mapping (.NET + Angular)
| Feature | Usage |
|---|---|
| Discount logic | Decorator |
| Tax calculation | Decorator |
| Logging | Decorator |
| Validation pipeline | Decorator |
Pro Tip (Advanced .NET Usage)
- Combine with Middleware pattern (ASP.NET Core pipeline)
- Useful in cross-cutting concerns like logging, caching
- Can integrate with DI for flexible composition
Summary
Decorator Pattern helps you:
- Extend behavior dynamically
- Keep core classes clean
- Build flexible and scalable systems
👉 Perfect for pricing, logging, validation, middleware pipelines
Comments
Post a Comment