The Notification Service

Step 4: The Notification Service

The factory decides which notifier to build; the service is the code that uses it. By taking a factory as a constructor argument, NotificationService never names a concrete notifier class. It just asks the factory. This is the payoff of the pattern: the dispatch logic is written once and works for every channel, present or future.

Build NotificationService:

  • init(self, factory) stores the factory
  • notify(channel, message) asks the factory to create the notifier for channel, calls its send(message), and returns that result

If the channel is unknown, the ValueError from the factory should propagate naturally. Do not catch it.

Hints
Starter code
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):
        self._registry[channel] = cls

    def create(self, channel):
        if channel not in self._registry:
            raise ValueError("unknown channel: " + str(channel))
        return self._registry[channel]()


class NotificationService:
    def __init__(self, factory):
        self._factory = factory

    def notify(self, channel, message):
        """Build a notifier via the factory and return its send result."""
        # TODO: hand the channel to self._factory so it builds the notifier for
        # you, then give back exactly what that notifier produces when asked to
        # send the message. An unknown channel's ValueError should escape here
        # uncaught, so do not wrap this in error handling.
        pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.