
In software development, one of the most critical design principles is ensuring that code is easy to maintain, extend, and test. The Factory Design Pattern is a widely used creational pattern that provides a way to create objects while hiding the creation logic from the client.
In this post, we’ll dive into the Factory Design Pattern, explain its importance, and demonstrate how to implement it in a .NET 8 API using a real-world example.
The Factory Design Pattern is a creational pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. It’s like a factory where you provide an input (the product type), and the factory determines how to create the correct product based on that input.
Now, let’s implement the Factory Design Pattern step by step in a .NET 8 API.
Imagine we’re building an API where we need to handle notifications. The notifications can be sent via different channels like Email, SMS, or Push Notifications, each having its implementation. Using the Factory Design Pattern, we can dynamically create the appropriate notification handler.
INotification
InterfaceThe first step is to define an interface that all notification types will implement:
public interface INotification{void Send(string to, string message);}
This interface ensures that every notification type (email, SMS, push) has a Send
method.
Now, we create concrete classes for each notification type:
public class EmailNotification : INotification{public void Send(string to, string message){Console.WriteLine($"Sending Email to {to}: {message}");}}public class SmsNotification : INotification{public void Send(string to, string message){Console.WriteLine($"Sending SMS to {to}: {message}");}}public class PushNotification : INotification{public void Send(string to, string message){Console.WriteLine($"Sending Push Notification to {to}: {message}");}}
NotificationFactory
The NotificationFactory
class is responsible for determining which notification handler to use based on the input type:
public class NotificationFactory{public INotification CreateNotification(string type){return type.ToLower() switch{"email" => new EmailNotification(),"sms" => new SmsNotification(),"push" => new PushNotification(),_ => throw new InvalidOperationException("Invalid notification type")};}}
This factory will return the appropriate notification object based on the input.
Now, let’s add a controller to handle the incoming requests. The controller uses the NotificationFactory
to send notifications.
[ApiController][Route("api/[controller]")]public class NotificationController : ControllerBase{private readonly NotificationFactory _notificationFactory;public NotificationController(){_notificationFactory = new NotificationFactory();}[HttpPost]public IActionResult SendNotification([FromBody] NotificationRequest request){var notification = _notificationFactory.CreateNotification(request.Type);notification.Send(request.To, request.Message);return Ok("Notification sent");}}public class NotificationRequest{public string Type { get; set; } // Email, SMS, Pushpublic string To { get; set; }public string Message { get; set; }}
The NotificationRequest
class is a simple model that contains the notification type, the recipient (To
), and the message:
public class NotificationRequest{public string Type { get; set; } // Can be "email", "sms", "push"public string To { get; set; }public string Message { get; set; }}
You can refactor the controller to use Dependency Injection (DI) for injecting the factory.
In Program.cs
:
builder.Services.AddSingleton<NotificationFactory>();
Modify the controller to accept the factory through the constructor:
public NotificationController(NotificationFactory notificationFactory){_notificationFactory = notificationFactory;}
To test the API, you can send a POST
request to /api/Notification
with the following JSON body to test different notification types.
For an email notification:
{"type": "email","to": "user@example.com","message": "Hello via Email!"}
For SMS:
{"type": "sms","to": "+1234567890","message": "Hello via SMS!"}
For Push Notification:
{"type": "push","to": "device_token","message": "Hello via Push Notification!"}
In this post, we implemented the Factory Design Pattern in a .NET 8 API. We learned how the factory pattern works and how it provides an abstraction for object creation. We also saw how this pattern enhances maintainability and extensibility by decoupling the object creation logic from the client code.
The Factory Pattern is a powerful design pattern that is particularly useful when you need to manage object creation dynamically and need the flexibility to introduce new types easily. This makes it a valuable tool for building scalable, maintainable APIs.
Your insights drive us! For any questions, feedback, or thoughts, feel free to connect:
If you found this guide beneficial, don’t hesitate to share it with your network. Until the next guide, happy coding!
Quick Links
Legal Stuff