Padrão Chain of Responsibility em Python
Published: 2020-12-14 22:45:08

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
```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
```
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. 

```python
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)

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

```python
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="")
```
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](https://diogomoreira.gitbook.io/padroes-de-projeto/) (Diogo Moreira, 2020)
[Mergulho nos Padrões de Projeto - v2020-1.14](https://refactoring.guru/pt-br/design-patterns/book) (Alexander Shvets, 2020)
*Os códigos usados como exemplo foram retirados do livro Mergulho nos Padrões de Projeto.*