from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Optional
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("chain_of_responsibility")
[docs]
class Handler(ABC):
"""
Abstract Handler interface for processing requests in the chain.
"""
[docs]
def __init__(self):
"""
Initializes the handler with no next handler in the chain.
"""
self._next_handler: Optional[Handler] = None
[docs]
def set_next(self, handler: Handler) -> Handler:
"""
Sets the next handler in the chain.
:param handler: The next handler.
:return: The handler itself, to allow method chaining.
"""
self._next_handler = handler
return handler
[docs]
@abstractmethod
def handle_request(self, request: str) -> None:
"""
Handles the request or forwards it to the next handler.
:param request: The request to handle.
"""
pass
[docs]
class AbstractHandler(Handler):
"""
Abstract base class that implements the chaining mechanism.
"""
[docs]
def handle_request(self, request: str) -> None:
"""
Forwards the request to the next handler if available.
:param request: The request to handle.
"""
if self._next_handler:
self._next_handler.handle_request(request)
[docs]
class ConcreteHandlerA(AbstractHandler):
"""
A concrete handler that processes requests matching 'A'.
"""
[docs]
def handle_request(self, request: str) -> None:
"""
Handles the request if applicable or forwards it to the next handler.
:param request: The request to handle.
"""
if request == 'A':
logger.info(f"ConcreteHandlerA handled request: {request}")
else:
logger.info(f"ConcreteHandlerA passing request: {request}")
super().handle_request(request)
[docs]
class ConcreteHandlerB(AbstractHandler):
"""
A concrete handler that processes requests matching 'B'.
"""
[docs]
def handle_request(self, request: str) -> None:
"""
Handles the request if it matches 'B', otherwise forwards it to the next handler.
:param request: The request to handle.
"""
if request == 'B':
logger.info(f"ConcreteHandlerB handled request: {request}")
else:
logger.info(f"ConcreteHandlerB passing request: {request}")
super().handle_request(request)