The function from Step 2 works, but adding a channel means editing its body. A registry-based factory fixes that: channels register themselves into a lookup table, and the factory builds from the table. New channels plug in without touching factory code, the open/closed principle in action.
Build NotifierFactory around an internal dict:
Because create instantiates the stored class, any notifier. Even one defined later. Works as long as it has been registered.
Note: each test below builds its own fresh NotifierFactory, so no registration leaks between tests.
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):
if channel == "email":
return EmailNotifier()
if channel == "sms":
return SmsNotifier()
if channel == "push":
return PushNotifier()
raise ValueError("unknown channel: " + str(channel))
class NotifierFactory:
def __init__(self):
self._registry = {}
def register(self, channel, cls):
"""Store cls under channel so create can build it later."""
# TODO: self._registry[channel] = cls
pass
def create(self, channel):
"""Build a fresh notifier from the registry, or raise ValueError."""
# TODO:
# if channel not in self._registry: raise ValueError(...)
# return self._registry[channel]()
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
The function from Step 2 works, but adding a channel means editing its body. A registry-based factory fixes that: channels register themselves into a lookup table, and the factory builds from the table. New channels plug in without touching factory code, the open/closed principle in action.
Build NotifierFactory around an internal dict:
Because create instantiates the stored class, any notifier. Even one defined later. Works as long as it has been registered.
Note: each test below builds its own fresh NotifierFactory, so no registration leaks between tests.
Press Run Tests or ββ© to check your solution.