Skip to content

Chain of Responsibility Pattern

Chain of Responsibility Pattern is a behavioral design pattern that allows you to pass requests along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain. This pattern is useful when you have a chain of handlers and you want to process the request by the first handler that can handle it.

For example, before checkout, you want to check if the order is fraudulent, if the stock is available, if the coupon is valid, etc. With Chain of Responsibility pattern, you can easily add a new handler without changing the existing code. Here is an example of Chain of Responsibility pattern in Python:

python
class Order:
    def __init__(self, amount: float, stock: int, coupon_code: str):
        self.amount = amount
        self.stock = stock
        self.coupon_code = coupon_code

class OrderHandler:
    def __init__(self, next_handler: 'OrderHandler' = None):
        self.next_handler = next_handler
    
    def set_next_handler(self, next_handler: 'OrderHandler'):
        self.next_handler = next_handler

    def handle(self, order: Order) -> None:
        pass

class FraudCheckerHandler(OrderHandler):
    def handle(self, order: Order) -> None:
        print("[FraudCheckerHandler] Checking for fraud...")
        if order.amount > 1000:
            print("[FraudCheckerHandler] Amount is too high, order cancelled")
            return
        if self.next_handler:
            self.next_handler.handle(order)

class StockCheckHandler(OrderHandler):
    def handle(self, order: Order) -> None:
        print("[StockCheckHandler] Checking for stock...")
        if order.stock == 0:
            print("[StockCheckHandler] Stock is out, order cancelled")
            return
        if self.next_handler:
            self.next_handler.handle(order)

class CouponCheckerHandler(OrderHandler):
    def handle(self, order: Order) -> None:
        print("[CouponCheckerHandler] Checking for coupon...")
        if order.coupon_code == "EXPIRED":
            print("[CouponCheckerHandler] Coupon is invalid, order cancelled")
            return
        if self.next_handler:
            self.next_handler.handle(order)

print("[Main] Starting the program")
fraud_checker = FraudCheckerHandler()
stock_check = StockCheckHandler()
coupon_checker = CouponCheckerHandler()
fraud_checker.set_next_handler(stock_check)
stock_check.set_next_handler(coupon_checker)
fraud_checker.handle(Order(amount=100, stock=10, coupon_code="VALID"))
fraud_checker.handle(Order(amount=100_000, stock=10, coupon_code="VALID"))
print("[Main] Program ended")

Here is the output of the program:

[Main] Starting the program
[FraudCheckerHandler] Checking for fraud...
[StockCheckHandler] Checking for stock...
[CouponCheckerHandler] Checking for coupon...
[FraudCheckerHandler] Checking for fraud...
[FraudCheckerHandler] Amount is too high, order cancelled
[Main] Program ended