Decorator Design Pattern in .NET
The Decorator pattern allows you to add new behavior to objects dynamically without modifying their structure. It wraps an object to enhance or alter its behavior at runtime.
Purpose
To extend the
functionality of objects in a flexible and reusable way without
changing the original class code.
Key Characteristics
- Uses composition,
not inheritance
- Decorators implement
the same interface as the target object
- Can be
stacked or chained to combine behaviors
Pros
- Adds
behavior without modifying existing classes
- Supports open/closed
principle
- Allows dynamic
behavior composition
Cons
- Many small
classes can increase complexity
- Can be
harder to trace behavior flow when deeply nested
Use Cases
- Adding
features like logging, security, or validation to financial
operations
- Applying transaction
fees, taxes, or discounts dynamically
- Decorating notifications
with audit trails or message formatting
Real-Time Finance Example: Adding Tax and
Discount to a Payment
Let’s say you
want to process a base payment and dynamically add tax and/or discount
without modifying the core payment class.
1. Define the Component Interface
public interface IPayment
{
decimal GetAmount();
}
2. Create the Concrete Component
public class BasePayment : IPayment
{
private readonly decimal _amount;
public BasePayment(decimal amount)
{
_amount = amount;
}
public decimal GetAmount() => _amount;
}
3. Create the Base Decorator
public abstract class PaymentDecorator :
IPayment
{
protected readonly IPayment _payment;
protected PaymentDecorator(IPayment payment)
{
_payment = payment;
}
public
abstract decimal GetAmount();
}
4. Create Concrete Decorators
public class TaxDecorator : PaymentDecorator
{
public TaxDecorator(IPayment payment) : base(payment) { }
public override decimal GetAmount()
{
decimal baseAmount = _payment.GetAmount();
decimal tax = baseAmount * 0.18m; // 18% GST
return baseAmount + tax;
}
}
public class DiscountDecorator :
PaymentDecorator
{
public DiscountDecorator(IPayment payment) : base(payment) { }
public override decimal GetAmount()
{
decimal baseAmount = _payment.GetAmount();
decimal discount = baseAmount * 0.10m; // 10% discount
return baseAmount - discount;
}
}
5. Client Code Usage
class Program
{
static void Main()
{
IPayment payment = new BasePayment(1000); // Base amount: ₹1000
// Add 18% tax
payment = new TaxDecorator(payment);
// Then apply 10% discount on total (after tax)
payment = new DiscountDecorator(payment);
Console.WriteLine($"Final Amount Payable:
₹{payment.GetAmount():0.00}");
}
}
Output
Final Amount Payable: ₹1062.00
Summary
- Decorator
Pattern lets you add
features dynamically, useful for things like taxes, fees, validation,
or logging
- In finance
systems, this is ideal for calculating charges, offers, or
enhancements without modifying core logic
- Promotes cleaner
and modular code
Comments
Post a Comment