Design Patterns in .NET Core and Their Alternatives
In .NET Core, design patterns are commonly used as alternatives to
complex code structures like large if-else blocks,
tight coupling, duplicated logic, and difficult-to-maintain code.
| Design Pattern | Alternative For | Purpose |
|---|---|---|
| Factory Pattern | Large if-else / switch statements | Centralizes object creation logic |
| Strategy Pattern | Behavior-based if-else conditions | Makes algorithms interchangeable |
| State Pattern | Complex state condition checks | Encapsulates state-specific behavior |
| Command Pattern | Direct method calls | Decouples request from execution |
| Repository Pattern | Scattered database queries | Abstracts data access logic |
| Unit of Work | Multiple transaction handling | Centralizes transaction management |
| Dependency Injection | Frequent use of new keyword | Provides loose coupling |
| Singleton Pattern | Global static objects | Ensures single instance creation |
| Observer Pattern | Tightly coupled event handling | Implements publish-subscribe model |
| Decorator Pattern | Large inheritance hierarchies | Adds behavior dynamically |
| Adapter Pattern | Incompatible interfaces | Connects incompatible classes |
| Facade Pattern | Complex subsystem calls | Provides simplified interface |
| Builder Pattern | Constructors with many parameters | Builds complex objects step-by-step |
| Prototype Pattern | Repeated object creation | Clones existing objects |
| Mediator Pattern | Direct communication between objects | Centralizes communication |
| Chain of Responsibility | Nested validations/checks | Processes requests through handlers |
| Template Method | Duplicate workflow logic | Reuses common algorithm structure |
| Specification Pattern | Repeated filtering conditions | Creates reusable query rules |
| CQRS | Single bloated service layer | Separates read and write operations |
Examples
1. Factory Pattern
Alternative for: if-else object creation
if(type == "pdf")
service = new PdfService();
else if(type == "excel")
service = new ExcelService();
Using Factory:
var service = reportFactory.Create(type);
2. Strategy Pattern
Alternative for: behavior-based conditions
if(paymentType == "Card")
ProcessCard();
else if(paymentType == "UPI")
ProcessUPI();
Using Strategy:
paymentStrategy.Process();
3. Builder Pattern
Alternative for: constructors with too many parameters
new User("John", 25, true, "Admin", "India");
Using Builder:
var user = new UserBuilder()
.WithName("John")
.WithAge(25)
.Build();
Conclusion
Design patterns in .NET Core are mainly alternatives for:
- Large if-else blocks
- Tight coupling
- Repeated code
- Complex object creation
- Difficult testing
- Rigid architecture
Using proper design patterns makes applications more scalable, maintainable, reusable, and testable.
Examples of Design Patterns in .NET Core
1. Factory Pattern
Alternative for: Large if-else or switch statements
if(type == "pdf")
service = new PdfService();
else if(type == "excel")
service = new ExcelService();
Using Factory:
var service = reportFactory.Create(type);
2. Strategy Pattern
Alternative for: Behavior-based if-else conditions
if(paymentType == "Card")
ProcessCard();
else if(paymentType == "UPI")
ProcessUPI();
Using Strategy:
paymentStrategy.Process();
3. State Pattern
Alternative for: State-based condition checking
if(order.Status == "Pending")
Approve();
else if(order.Status == "Shipped")
Deliver();
Using State Pattern:
orderState.Handle(order);
4. Command Pattern
Alternative for: Direct method calls
button.Click += SaveFile;
Using Command:
ICommand command = new SaveCommand(); command.Execute();
5. Repository Pattern
Alternative for: Direct database queries everywhere
var users = _context.Users.ToList();
Using Repository:
var users = userRepository.GetAll();
6. Unit of Work Pattern
Alternative for: Multiple scattered SaveChanges()
_context.Users.Add(user); _context.SaveChanges(); _context.Orders.Add(order); _context.SaveChanges();
Using Unit of Work:
unitOfWork.Users.Add(user); unitOfWork.Orders.Add(order); unitOfWork.Commit();
7. Dependency Injection
Alternative for: Frequent use of new keyword
var service = new EmailService();
Using DI:
public UserController(IEmailService service)
{
_service = service;
}
8. Singleton Pattern
Alternative for: Global static objects
public static Logger logger = new Logger();
Using Singleton:
var logger = Logger.Instance;
9. Observer Pattern
Alternative for: Tight event coupling
user.SendEmail(); user.SendSMS();
Using Observer:
publisher.NotifySubscribers();
10. Decorator Pattern
Alternative for: Large inheritance hierarchy
class PremiumCoffee : MilkCoffee
Using Decorator:
coffee = new MilkDecorator(coffee); coffee = new SugarDecorator(coffee);
11. Adapter Pattern
Alternative for: Incompatible interfaces
OldPaymentGateway.Pay();
Using Adapter:
adapter.ProcessPayment();
12. Facade Pattern
Alternative for: Complex subsystem calls
cpu.Start(); memory.Load(); disk.Read();
Using Facade:
computer.Start();
13. Builder Pattern
Alternative for: Constructors with many parameters
new User("John", 25, true, "Admin");
Using Builder:
var user = new UserBuilder()
.WithName("John")
.WithAge(25)
.Build();
14. Prototype Pattern
Alternative for: Recreating same object repeatedly
var user = new User();
Using Prototype:
var clonedUser = existingUser.Clone();
15. Mediator Pattern
Alternative for: Objects communicating directly
user.Notify(admin); admin.Notify(manager);
Using Mediator:
mediator.SendMessage(message);
16. Chain of Responsibility
Alternative for: Nested validations
if(isValidUser)
{
if(hasPermission)
{
if(isActive)
{
}
}
}
Using Chain Pattern:
handler.Handle(request);
17. Template Method
Alternative for: Duplicate workflow logic
ProcessCSV(); ProcessExcel();
Using Template Method:
processor.ProcessFile();
18. Specification Pattern
Alternative for: Repeated filtering conditions
users.Where(x => x.IsActive && x.Age > 18);
Using Specification:
repository.Find(activeAdultSpecification);
19. CQRS Pattern
Alternative for: One large service handling everything
UserService.CreateUser(); UserService.GetUsers();
Using CQRS:
CreateUserCommand GetUsersQuery
Summary
Design patterns are mainly alternatives for:
- Large if-else blocks
- Tight coupling
- Code duplication
- Complex constructors
- Scattered database logic
- Hard-to-maintain architecture
Comments
Post a Comment