Card 04/ 09
Factory Method Example: A Notification Sender per Channel
The order code sends a notification; each channel's subclass decides whether it is an email or an SMS.
An order system that sends shipping notices is a natural Factory Method, and this example maps the template onto it. It tells customers their order has shipped, by email for some and by SMS for others. The message and the moment it is sent are the same for both. The only difference is which kind of sender is created, which is exactly the decision the pattern hands to a subclass.
| Participant | Class in this example |
|---|---|
| Product | Sender, with one method send(text) |
| ConcreteProduct | EmailSender and SmsSender |
| Creator | OrderNotifier, whose notify_shipped calls the factory method |
| ConcreteCreator | EmailOrderNotifier and SmsOrderNotifier |
| Factory method | create_sender |
from abc import ABC, abstractmethod
class Sender(ABC):
@abstractmethod
def send(self, text: str) -> str: ...
class EmailSender(Sender):
def send(self, text: str) -> str:
return f"email to [email protected]: {text}"
class SmsSender(Sender):
def send(self, text: str) -> str:
return f"SMS to +44 7700 900123: {text}"
class OrderNotifier(ABC):
@abstractmethod
def create_sender(self) -> Sender: ...
def notify_shipped(self, order_id: str) -> None:
sender = self.create_sender()
print(sender.send(f"Order {order_id} has shipped and will arrive in two days."))
class EmailOrderNotifier(OrderNotifier):
def create_sender(self) -> Sender:
return EmailSender()
class SmsOrderNotifier(OrderNotifier):
def create_sender(self) -> Sender:
return SmsSender()
EmailOrderNotifier().notify_shipped("A-1042")
SmsOrderNotifier().notify_shipped("A-1042")email to [email protected]: Order A-1042 has shipped and will arrive in two days.
SMS to +44 7700 900123: Order A-1042 has shipped and will arrive in two days.notify_shipped builds the message and sends it, and it does not know which channel it is using. Adding push notifications later means a PushSender and a PushOrderNotifier, and no edit to the code that already sends email and SMS.
The creator has a domain name, OrderNotifier, not a pattern name. That is typical, and it is why the pattern is often missed in real code: you recognise it by the shape, an overridable method that returns an object through an interface, rather than by a class called Factory.
← → move through sections and cards