The chain of responsibility pattern inside Python allows us to build an application with loose coupling in mind. This is achieved by passing a received request through a chain of objects inside the software.
The following code snippet shows the implementation of the chain of responsibility pattern inside Python:
import abc class Handler(metaclass=abc.ABCMeta): """Handler provides an interface to build handlers.""" def __init__(self, handler=None): """Initialize the handler. Keyword arguments: handler -- The next handler object to be called """ self._next_handler = handler @abc.abstractmethod def handler(self, data): """The handler abstract method. Keyword arguments: data -- The data to be processed by the handler """ pass class StringHandler(Handler): """String type object handler.""" def handler(self, data): if type(data) is str: print("Stringt type data found.") elif self._next_handler is not None: self._next_handler.handler(data) else: raise Exception("Unable to find a suitable handler for data.") class IntegerHandler(Handler): """Integer type object handler.""" def handler(self, data): if type(data) is int: print("Integer type data found") elif self._next_handler is not None: self._next_handler.handler(data) else: raise Exception("Unable to find a suitable handler for data.") if __name__ == '__main__': int_handler = IntegerHandler() str_handler = StringHandler(int_handler) str_handler.handler(2)
The __new__
method is the first method that's called when a new instance of an object needs to be created, whereas the __init__
method is run only when the newly created instance of the object needs to be initialized. In the normal flow of class instance creation, the __new__
method will always be executed first and should only be overridden when the developer wants to gain control over the creation of new instances. This method should then be followed by a call to the __init__
method, which will be called once the instance has been created and will need to be initialized.
It's quite easy to define a new abstract class using the ABC metaclass. The following code snippet shows an example of achieving this kind of behavior:
import abc class Handler(metaclass=abc.ABCMeta): """Handler provides an interface to build handlers.""" def __init__(self, handler=None): """Initialize the handler. Keyword arguments: handler -- The next handler object to be called """ self._next_handler = handler @abc.abstractmethod def handler(self, data): """The handler abstract method. Keyword arguments: data -- The data to be processed by the handler """ pass