Introduction
Design patterns are proven solutions to common software design problems. They help you write:
Clean code
Maintainable systems
Scalable applications
In modern development with .NET 9, design patterns are widely used in:
ASP.NET Core APIs
Microservices
Blazor applications
Enterprise systems
π§ What Are Design Patterns?
Design patterns are templates or best practices, not ready-made code.
π They solve problems like:
π· Types of Design Patterns
1. Creational Patterns
π Handle object creation
2. Structural Patterns
π Organize classes and objects
3. Behavioral Patterns
π Manage communication
π₯ Most Useful Patterns in .NET 9 (with Examples)
πΉ 1. Singleton Pattern
π Use Case
Logging service
Configuration manager
β
Example
public class Logger
{
private static Logger _instance;
private Logger() { }
public static Logger Instance
{
get
{
if (_instance == null)
_instance = new Logger();
return _instance;
}
}
public void Log(string message)
{
Console.WriteLine(message);
}
}
π‘ .NET 9 Best Practice
π Use Dependency Injection instead:
builder.Services.AddSingleton<Logger>();
πΉ 2. Factory Pattern
π Use Case
β
Example
public interface INotification
{
void Send();
}
public class EmailNotification : INotification
{
public void Send() => Console.WriteLine("Email Sent");
}
public class SmsNotification : INotification
{
public void Send() => Console.WriteLine("SMS Sent");
}
public class NotificationFactory
{
public static INotification Create(string type)
{
return type switch
{
"email" => new EmailNotification(),
"sms" => new SmsNotification(),
_ => throw new Exception("Invalid type")
};
}
}
πΉ 3. Repository Pattern
π Use Case
β
Example
public interface IProductRepository
{
Task<Product> GetById(int id);
}
public class ProductRepository : IProductRepository
{
public async Task<Product> GetById(int id)
{
// DB logic here
return new Product();
}
}
π Register in .NET 9:
builder.Services.AddScoped<IProductRepository, ProductRepository>();
πΉ 4. Dependency Injection (DI)
π Built-in in .NET 9
π Core of modern .NET apps
public class OrderService
{
private readonly IProductRepository _repo;
public OrderService(IProductRepository repo)
{
_repo = repo;
}
}
β‘ Benefit
Loose coupling
Easy testing
Clean architecture
πΉ 5. Strategy Pattern
π Use Case
β
Example
public interface IPaymentStrategy
{
void Pay();
}
public class CreditCardPayment : IPaymentStrategy
{
public void Pay() => Console.WriteLine("Paid via Credit Card");
}
public class UpiPayment : IPaymentStrategy
{
public void Pay() => Console.WriteLine("Paid via UPI");
}
π Usage:
public class PaymentContext
{
private readonly IPaymentStrategy _strategy;
public PaymentContext(IPaymentStrategy strategy)
{
_strategy = strategy;
}
public void Execute() => _strategy.Pay();
}
πΉ 6. Observer Pattern
π Use Case
Event-driven systems
Notifications
β
Example (using events)
public class Publisher
{
public event Action OnChange;
public void Notify()
{
OnChange?.Invoke();
}
}
πΉ 7. Mediator Pattern (Used in CQRS)
π Common with libraries like MediatR
π Use Case
public class CreateOrderCommand
{
public int Id { get; set; }
}
π§© Real-World Architecture in .NET 9
Typical clean architecture uses:
β οΈ Common Mistakes
β Overusing patterns (over-engineering)
β Using Singleton incorrectly (thread issues)
β Ignoring built-in DI
β Mixing business logic with data access
π― When to Use Patterns?
| Problem | Pattern |
|---|
| Object creation logic | Factory |
| Shared instance | Singleton |
| Multiple behaviors | Strategy |
| Loose coupling | DI |
| Data abstraction | Repository |
π Interview Questions
What is Dependency Injection in .NET 9?
Difference between Factory and Strategy?
Why Repository pattern is used?
What problems does Singleton solve?
How does DI improve testability?
π Conclusion
Design patterns in .NET 9 are essential for building:
π Mastering these patterns will: