Chain of Responsibility Method

Chain of Responsibility Method

Chain of Responsibility Method

The chain of responsibility method is a type of behavioural design patterns that helps rearrange the conditional action blocks dynamically at each run-time. It could be seen as the object-oriented version of if__elif__elif__elif__else statement and helps to pass the request along the chain of handlers. This method recognizes the behaviour of one group of objects that indirectly call other objects using the same techniques, while other objects follow the standard interface.

Structure Of Chain of Responsibility

The structure of the chain of responsibility can be categorized into four connected parts, and they are:

  • Base Handler
    • it’s a class where you can put the code that is common to all handlers class.
  • Client
    • the client comprises the chains of responsibility dynamically.
  • Concrete Handlers
    • it contains the actual code for preprocessing request.
  • Handler
    • it carries a single method for handling request and also declares the interface common for all handlers.

Implementation

The Implementation of the chain of responsibility method is carried out in python:

class AbstractHandler(object): 
    """Parent class of all concrete handlers"""
    def __init__(self, nxt): 
        """change the local variable using nxt"""
        self._nxt = nxt 
    def handle(self, request): 
        """calling the processRequest through given request"""
        handled = self.processRequest(request) 
        """case when it is not handled"""
        if not handled: 
            self._nxt.handle(request) 
    def processRequest(self, request): 
        """throws a NotImplementedError"""
        raise NotImplementedError('First implement it !') 

class FirstConcreteHandler(AbstractHandler): 
    """Concrete Handler # 1"""
    def processRequest(self, request): 
        '''return True if request is handled '''
        if 'a' < request <= 'e': 
            print("\nThis is {} handling request '{}'".format(self.__class__.__name__, request)) 
            return True

class SecondConcreteHandler(AbstractHandler): 
    """Concrete Handler # 2"""
    def processRequest(self, request): 
        '''return True if the request is handled'''
        if 'e' < request <= 'l': 
            print("\nThis is {} handling request '{}'".format(self.__class__.__name__, request)) 
            return True

class ThirdConcreteHandler(AbstractHandler): 
    """Concrete Handler # 3"""
    def processRequest(self, request): 
        '''return True if the request is handled'''
        if 'l' < request <= 'z': 
            print("\nThis is {} handling request '{}'".format(self.__class__.__name__, request)) 
            return True

class DefaultHandler(AbstractHandler): 
    """Default Handler"""
    def processRequest(self, request): 
        """Gives the message that th request is not handled and returns true"""
        print("\nThis is {} telling you that request '{}' has no handler right now.".format(self.__class__.__name__, request)) 
        return True

class Client: 
    """Client Class"""
    def __init__(self): 
        """Provides the sequence of handles for the clients"""
        initial = None
        self.handler = FirstConcreteHandler(SecondConcreteHandler(ThirdConcreteHandler(DefaultHandler(initial)))) 
    def agent(self, client_request): 
        """Iterates over each request and sends them to specific handles"""
        for request in client_request: 
            self.handler.handle(request) 

"""main method"""
if __name__ == "__main__": 
    """Create a client object"""
    client = Client() 
    """Create requests to be processed"""
    string = "Python for Cybersecurity"
    requests = list(string) 
    """Send the requests one by one, to handlers as per the sequence of handlers defined in the Client class"""
    client.agent(requests)

Code output:

ProBook:~/InfosecAddicts/$ python chain.py

This is DefaultHandler telling you that request 'P' has no handler right now.

This is ThirdConcreteHandler handling request 'y'

This is ThirdConcreteHandler handling request 't'

This is SecondConcreteHandler handling request 'h'

This is ThirdConcreteHandler handling request 'o'

This is ThirdConcreteHandler handling request 'n'

This is DefaultHandler telling you that request ' ' has no handler right now.

This is SecondConcreteHandler handling request 'f'

This is ThirdConcreteHandler handling request 'o'

This is ThirdConcreteHandler handling request 'r'

This is DefaultHandler telling you that request ' ' has no handler right now.

This is DefaultHandler telling you that request 'C' has no handler right now.

This is ThirdConcreteHandler handling request 'y'

This is FirstConcreteHandler handling request 'b'

This is FirstConcreteHandler handling request 'e'

This is ThirdConcreteHandler handling request 'r'

This is ThirdConcreteHandler handling request 's'

This is FirstConcreteHandler handling request 'e'

This is FirstConcreteHandler handling request 'c'

This is ThirdConcreteHandler handling request 'u'

This is ThirdConcreteHandler handling request 'r'

This is SecondConcreteHandler handling request 'i'

This is ThirdConcreteHandler handling request 't'

This is ThirdConcreteHandler handling request 'y'

Pros and Cons

Pros
  • Increased Flexibility
  • Open/Closed Principle
  • Single Responsibility Principle
Cons
  • Low System Performance
  • Lack of visible functionalities
  • Unhandled request