Dispatcher pattern implementation and use cases: polymorphism, router.
from abc import ABC, abstractmethod | |
class Dispatcher(ABC): | |
@abstractmethod | |
def _get_key(): | |
raise NotImplementedError | |
@classmethod | |
def register(cls, key): | |
def wrapper(func): | |
cls._mapping[key] = func | |
return wrapper | |
@classmethod | |
def run(cls, *args): | |
key = cls._get_key(args) | |
if key not in cls._mapping: | |
raise ValueError | |
return cls._mapping[key](*args) | |
class Add(Dispatcher): | |
_mapping = {} | |
@staticmethod | |
def _get_key(args): | |
return type(args[0]) | |
class Get(Dispatcher): | |
_mapping = {} | |
@staticmethod | |
def _get_key(args): | |
return args[0] | |
@Add.register(int) | |
def _(*numbers): | |
return sum(numbers) | |
@Add.register(str) | |
def _(*words): | |
return ' '.join(words) | |
@Get.register('/') | |
def _(url, *params): | |
return 200, 'Welcome to the candy shop!' | |
@Get.register('/candies') | |
def _(url, *params): | |
colors = ['calisson', 'nougat', 'macaron'] | |
if not params: | |
return 200, {'candies': colors} | |
idx = params[0] | |
if idx in range(len(colors)): | |
return 200, {'candy': colors[idx]} | |
return 404, f'Candy `{idx}` not found.' | |
add = Add.run | |
assert add(1, 2, 3) == 6 | |
assert add('hello', 'world') == 'hello world' | |
get = Get.run | |
assert get('/') == 200, 'Welcome to the candy shop!' | |
assert get('/colors') == 200, {'candies': ['calisson', 'nougat', 'macaron']} | |
assert get('/colors', 0) == 200, {'candy': 'calisson'} | |
assert get('/colors', 4) == 404, 'Candy `4` not found.' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment