Fundamentals 11 min read

Understanding the Chain of Responsibility Design Pattern with Java Examples

This article introduces the Chain of Responsibility design pattern, explains its purpose and typical use cases, demonstrates common pitfalls with a naïve implementation, and provides step‑by‑step Java refactorings—including a basic chain, an abstract handler hierarchy, and a factory‑based configuration—to illustrate how to build flexible, maintainable processing pipelines.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding the Chain of Responsibility Design Pattern with Java Examples

Recently a team member implemented an import feature using the Chain of Responsibility pattern, resulting in overly complex code and many bugs; the author argues that the Template Method pattern would have been more appropriate and uses this as a motivation to explore the Chain of Responsibility.

What is the Chain of Responsibility?

The Chain of Responsibility is a behavioral design pattern that lets you pass a request along a chain of handlers, where each handler can either process the request or forward it to the next handler.

Use Cases

Multi‑condition flow control such as permission checks.

ERP workflow approvals (e.g., manager, HR manager, project manager).

Underlying implementation of Java servlet filters.

Anti‑example

A simple game with three levels is implemented using nested if statements, leading to repetitive and hard‑to‑maintain code. The article shows how this approach quickly becomes unmanageable as the number of levels grows.

public class FirstPassHandler {
    public int handler(){
        System.out.println("第一关-->FirstPassHandler");
        return 80;
    }
}
// ... similar classes for SecondPassHandler and ThirdPassHandler ...
public class HandlerClient {
    public static void main(String[] args){
        FirstPassHandler firstPassHandler = new FirstPassHandler();
        SecondPassHandler secondPassHandler = new SecondPassHandler();
        ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
        int firstScore = firstPassHandler.handler();
        if(firstScore >= 80){
            int secondScore = secondPassHandler.handler();
            if(secondScore >= 90){
                thirdPassHandler.handler();
            }
        }
    }
}

To avoid such duplication, the article proposes linking each level via a chain, so the client no longer needs multiple if checks.

public class FirstPassHandler extends AbstractHandler {
    private int play(){ return 80; }
    @Override
    public int handler(){
        System.out.println("第一关-->FirstPassHandler");
        int score = play();
        if(score >= 80 && this.next != null){
            return this.next.handler();
        }
        return score;
    }
}
// Similar implementations for SecondPassHandler and ThirdPassHandler
public abstract class AbstractHandler {
    protected AbstractHandler next;
    public void setNext(AbstractHandler next){ this.next = next; }
    public abstract int handler();
}
public class HandlerClient {
    public static void main(String[] args){
        FirstPassHandler first = new FirstPassHandler();
        SecondPassHandler second = new SecondPassHandler();
        ThirdPassHandler third = new ThirdPassHandler();
        first.setNext(second);
        second.setNext(third);
        first.handler();
    }
}

Drawbacks of the Initial Implementation

Each level holds a reference to a different concrete next‑level class, making the chain hard to extend.

The code is not easily scalable; adding or removing levels requires substantial changes.

Factory‑Based Refactoring

The article further demonstrates how to externalize the chain configuration into an enum and a factory, allowing dynamic assembly of handlers via reflection.

public enum GatewayEnum {
    API_HANDLER(new GatewayEntity(1, "api接口限流", "cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)),
    BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)),
    SESSION_HANDLER(new GatewayEntity(3, "用户会话拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null));
    // ... getters and constructor ...
}
// Factory that builds the chain using the enum configuration
public class GatewayHandlerEnumFactory {
    private static GatewayDao gatewayDao = new GatewayImpl();
    public static GatewayHandler getFirstGatewayHandler(){
        GatewayEntity firstEntity = gatewayDao.getFirstGatewayEntity();
        GatewayHandler firstHandler = newGatewayHandler(firstEntity);
        // link subsequent handlers based on nextHandlerId
        // ...
        return firstHandler;
    }
    private static GatewayHandler newGatewayHandler(GatewayEntity entity){
        try {
            Class<?> clazz = Class.forName(entity.getConference());
            return (GatewayHandler) clazz.newInstance();
        } catch (Exception e){ e.printStackTrace(); }
        return null;
    }
}

Conclusion

Design patterns like the Chain of Responsibility provide a structured way to handle flexible processing flows; mastering them is essential for writing clean, maintainable code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Chain of ResponsibilityDesign PatternsJavarefactoring
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.