Design Pattern

Chain of Responsibility Pattern

Clean Java-only production-ready implementation.


You have a sequence of processing steps. Each step handles the request or passes it to the next handler. The client doesn't know which handler eventually processes it — it just sends the request into the chain.

// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A server logs dispatcher routing message blocks to Info, Warning, and Error
// listeners.
//
// WHERE THE HANDLER FITS IN:
// LoggerHandler is the Handler base class. InfoLogger and ErrorLogger are
// Concrete Handlers delegating messages down the chain using .setNext().
// ────────────────────────────────────────────────────────────────────────────
// --- Handler ---
abstract class LogHandler {
    protected LogHandler next;

    public LogHandler setNext(LogHandler next) {
        this.next = next;
        return next;
    }

    public abstract void handle(String message, int level);
}

// --- Concrete handlers ---
class DebugLogHandler extends LogHandler {
    public void handle(String message, int level) {
        if (level <= 10) {
            System.out.println("  [DEBUG] " + message);
        } else if (next != null) {
            next.handle(message, level);
        }
    }
}

class InfoLogHandler extends LogHandler {
    public void handle(String message, int level) {
        if (level <= 20) {
            System.out.println("  [INFO] " + message);
        } else if (next != null) {
            next.handle(message, level);
        }
    }
}

class ErrorLogHandler extends LogHandler {
    public void handle(String message, int level) {
        if (level <= 30) {
            System.out.println("  [ERROR] " + message + " ⚠");
        } else if (next != null) {
            next.handle(message, level);
        }
    }
}

// --- Client builds the chain ---
public class Main {
    public static void main(String[] args) {
        LogHandler chain = new DebugLogHandler();
        chain.setNext(new InfoLogHandler())
             .setNext(new ErrorLogHandler());

        // Client just calls handle on the head of chain
        chain.handle("Starting system", 10);    // DEBUG
        chain.handle("User logged in", 20);      // INFO
        chain.handle("Payment failed!", 30);      // ERROR
    }
}