String de responsabilidad: patrones de diseño de Python

El método de la string de responsabilidad es un patrón de diseño conductual y es la versión orientada a objetos de if… elif… elif… else y nos permite reorganizar los bloques de condición-acción dinámicamente en tiempo de ejecución. Nos permite pasar las requests a lo largo de la string de controladores. El procesamiento es simple, cada vez que un controlador recibe la solicitud, tiene dos opciones: procesarla o pasarla al siguiente controlador de la string. 
Este patrón tiene como objetivo desacoplar a los remitentes de una solicitud de sus receptores al permitir que la solicitud se mueva a través de receptores enstringdos hasta que se maneje. 
 

método-de-la-string-de-responsabilidad

Problema sin utilizar el método de string de responsabilidad

Imagine que está creando un sitio web simple que toma strings de entrada e informa sobre las diversas propiedades de las strings, como el palíndromo de strings. ¿La string está en mayúsculas? ¿La string es minúscula? y muchas otras propiedades también. Después de la planificación completa, decide que estas comprobaciones de la string de entrada deben realizarse secuencialmente. Entonces, aquí surge el problema para el desarrollador que tiene que implementar una aplicación de este tipo que pueda decidir en tiempo de ejecución qué acción se debe realizar a continuación.
 

Solución utilizando el Método de la String de Responsabilidad

El método de la string de responsabilidad proporciona la solución para el problema descrito anteriormente. Crea un controlador abstracto separado que se usa para manejar las operaciones secuenciales que deben realizarse dinámicamente. Por ejemplo, creamos cuatro controladores llamados FirstConcreteHandler, SecondConcreteHandler, ThirdConcreteHandler y Defaulthandler y los llamamos secuencialmente desde la clase de usuario.
 

Python3

class AbstractHandler(object):
 
    """Parent class of all concrete handlers"""
 
    def __init__(self, nxt):
 
        """change or increase the local variable using nxt"""
 
        self._nxt = nxt
 
    def handle(self, request):
 
        """It calls 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: Child class of AbstractHandler"""
 
    def processRequest(self, request):
 
        '''return True if request is handled '''
 
        if 'a' < request <= 'e':
            print("This is {} handling request '{}'".format(self.__class__.__name__, request))
            return True
 
 
class SecondConcreteHandler(AbstractHandler):
 
    """Concrete Handler # 2: Child class of AbstractHandler"""
 
    def processRequest(self, request):
 
        '''return True if the request is handled'''
 
        if 'e' < request <= 'l':
            print("This is {} handling request '{}'".format(self.__class__.__name__, request))
            return True
 
class ThirdConcreteHandler(AbstractHandler):
 
    """Concrete Handler # 3: Child class of AbstractHandler"""
 
    def processRequest(self, request):
 
        '''return True if the request is handled'''
 
        if 'l' < request <= 'z':
            print("This is {} handling request '{}'".format(self.__class__.__name__, request))
            return True
 
class DefaultHandler(AbstractHandler):
 
    """Default Handler: child class from AbstractHandler"""
 
    def processRequest(self, request):
 
        """Gives the message that th request is not handled and returns true"""
 
        print("This is {} telling you that request '{}' has no handler right now.".format(self.__class__.__name__,
                                                                                          request))
        return True
 
 
class User:
 
    """User Class"""
 
    def __init__(self):
 
        """Provides the sequence of handles for the users"""
 
        initial = None
 
        self.handler = FirstConcreteHandler(SecondConcreteHandler(ThirdConcreteHandler(DefaultHandler(initial))))
 
    def agent(self, user_request):
 
        """Iterates over each request and sends them to specific handles"""
 
        for request in user_request:
            self.handler.handle(request)
 
"""main method"""
 
if __name__ == "__main__":
 
    """Create a client object"""
    user = User()
 
    """Create requests to be processed"""
 
    string = "GeeksforGeeks"
    requests = list(string)
 
    """Send the requests one by one, to handlers as per the sequence of handlers defined in the Client class"""
    user.agent(requests)

Producción

This is DefaultHandler telling you that request 'G' has no handler right now.
This is FirstConcreteHandler handling request 'e'
This is FirstConcreteHandler handling request 'e'
This is SecondConcreteHandler handling request 'k'
This is ThirdConcreteHandler handling request 's'
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 'G' has no handler right now.
This is FirstConcreteHandler handling request 'e'
This is FirstConcreteHandler handling request 'e'
This is SecondConcreteHandler handling request 'k'
This is ThirdConcreteHandler handling request 's'

Diagrama de clase

Diagrama de clases para el método de la string de responsabilidad
 

String-de-responsabilidad_clase_diagrama

Ventajas

  • Principio de responsabilidad única: aquí es fácil desacoplar las clases que invocan operaciones de las clases que realizan operaciones.
  • Principio abierto/cerrado: podemos introducir las nuevas clases de código sin romper el código del cliente existente.
  • Aumenta la flexibilidad: al otorgar las responsabilidades a los objetos, aumenta la flexibilidad del código.

Desventajas

  • Solicitud no asegurada: este método no proporciona ninguna garantía de si el objeto se recibirá o no.
  • Características de detección: debido a la depuración, se vuelve una tarea difícil observar las características de las operaciones.
  • Rendimiento del sistema depreciado: podría afectar el rendimiento del sistema debido a las llamadas de ciclo continuo

Aplicabilidad

  • Procesamiento de varios manejadores en orden: el método de la string de responsabilidad ayuda mucho cuando se requiere procesar varios manejadores en un orden particular porque la vinculación es posible en cualquier orden
  • Requests de desacoplamiento: este método generalmente se usa cuando desea desacoplar el remitente y el receptor de la solicitud.
  • Controladores no especificados: cuando no desea especificar controladores en el código, siempre se prefiere usar la String de responsabilidad .

Lectura adicional: string de responsabilidad en Java
 

Publicación traducida automáticamente

Artículo escrito por chaudhary_19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *