DEV Community

Michel Moreira
Michel Moreira

Posted on • Updated on

Padrão Chain of Responsibility em Python

O Chain of Responsibility é um padrão de projeto comportamental, ele permite que uma requisição seja passada por uma quantidade de handlers (objetos solitários com comportamentos específicos).

Cada um desses handlers possui um campo que armazena uma referência ao próximo, sendo assim, além de processar o pedido ele pode passar (ou não) o pedido a diante, criando uma corrente de execução.

Exemplo de Chain of Responsibility em Python

class Handler(ABC):

    @abstractmethod
    def set_next(self, handler: Handler) -> Handler:
        pass

    @abstractmethod
    def handle(self, request) -> Optional[str]:
        pass

class AbstractHandler(Handler):

    _next_handler: Handler = None

    def set_next(self, handler: Handler) -> Handler:
        self._next_handler = handler
        return handler

    @abstractmethod
    def handle(self, request: Any) -> str:
        if self._next_handler:
            return self._next_handler.handle(request)

        return None
Enter fullscreen mode Exit fullscreen mode

A classe Handler representa uma interface que será comum para todos os handlers. Esta possui um método para lidar com a requisição e outro método opcional que configura o próximo handler da corrente.

A classe AbstractHendler é onde é implementado o código que é comum para todos os handlers, esta também possui o campo onde é armazenada a referência para o próximo handler.

class MonkeyHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Banana":
            return f"Monkey: I'll eat the {request}"
        else:
            return super().handle(request)


class SquirrelHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "Nut":
            return f"Squirrel: I'll eat the {request}"
        else:
            return super().handle(request)


class DogHandler(AbstractHandler):
    def handle(self, request: Any) -> str:
        if request == "MeatBall":
            return f"Dog: I'll eat the {request}"
        else:
            return super().handle(request)

Enter fullscreen mode Exit fullscreen mode

Estas classes representam exemplos de implementações de handlers, estes contém a maneira particular de cada um de lidar com a requisição.

def client_code(handler: Handler) -> None:

    for food in ["Nut", "Banana", "Cup of coffee"]:
        print(f"\nClient: Who wants a {food}?")
        result = handler.handle(food)
        if result:
            print(f"  {result}", end="")
        else:
            print(f"  {food} was left untouched.", end="")
Enter fullscreen mode Exit fullscreen mode

Por fim o código do cliente, este compõe as correntes dependendo da lógica da aplicação.

O uso do padrão Chain of Responsibility é indicado quando existe a necessidade de processamento de diferentes tipos de pedidos de várias maneiras, independendo dos tipos ou sequência específica. Também é recomendado o seu uso quando precisa-se executar várias handlers em uma ordem específica.

A implementação em Python não tem nenhuma particularidade em relação a implementação em Java.


Referências
Padrões de Projeto (Diogo Moreira, 2020)
Mergulho nos Padrões de Projeto - v2020-1.14 (Alexander Shvets, 2020)
Os códigos usados como exemplo foram retirados do livro Mergulho nos Padrões de Projeto.

Top comments (0)