.NET  

Design Patterns and How to Use Them in .NET 9 Applications

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:

  • Object creation

  • Code structure

  • Communication between components

πŸ”· Types of Design Patterns

1. Creational Patterns

πŸ‘‰ Handle object creation

  • Singleton

  • Factory

  • Builder

2. Structural Patterns

πŸ‘‰ Organize classes and objects

  • Adapter

  • Decorator

  • Facade

3. Behavioral Patterns

πŸ‘‰ Manage communication

  • Observer

  • Strategy

  • Mediator

πŸ”₯ 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

  • Creating objects based on conditions

βœ… 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

  • Data access abstraction

βœ… 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

  • Multiple algorithms (runtime selection)

βœ… 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

  • Decoupling components

public class CreateOrderCommand
{
    public int Id { get; set; }
}

🧩 Real-World Architecture in .NET 9

Typical clean architecture uses:

  • Controller β†’ Service β†’ Repository

  • DI + Factory + Strategy combined

⚠️ 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?

ProblemPattern
Object creation logicFactory
Shared instanceSingleton
Multiple behaviorsStrategy
Loose couplingDI
Data abstractionRepository

πŸš€ 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:

  • Scalable systems

  • Maintainable codebases

  • Enterprise-level applications

πŸ‘‰ Mastering these patterns will:

  • Boost your coding skills

  • Help in interviews

  • Make you think like a senior developer