Right now a caller who wants an email notifier must write EmailNotifier(). It hard-codes the class. Change the channel and you edit every call site. The Factory pattern removes that coupling: callers name a channel as a string, and one function decides which class to build.
Add a third concrete notifier, PushNotifier (send returns {"channel": "push", "message": message}), then write the factory function.
Each call must return a new instance, and unknown channels must fail loudly rather than returning None.
class Notifier:
def send(self, message):
raise NotImplementedError
class EmailNotifier(Notifier):
def send(self, message):
return {"channel": "email", "message": message}
class SmsNotifier(Notifier):
def send(self, message):
return {"channel": "sms", "message": message}
class PushNotifier(Notifier):
def send(self, message):
return {"channel": "push", "message": message}
def notifier_for(channel):
"""Return a fresh notifier matching channel, or raise ValueError."""
# TODO:
# if channel == "email": return EmailNotifier()
# if channel == "sms": return SmsNotifier()
# if channel == "push": return PushNotifier()
# raise ValueError for anything else
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Right now a caller who wants an email notifier must write EmailNotifier(). It hard-codes the class. Change the channel and you edit every call site. The Factory pattern removes that coupling: callers name a channel as a string, and one function decides which class to build.
Add a third concrete notifier, PushNotifier (send returns {"channel": "push", "message": message}), then write the factory function.
Each call must return a new instance, and unknown channels must fail loudly rather than returning None.
Press Run Tests or ββ© to check your solution.