Backend Development 11 min read

Chain of Responsibility Pattern in Java: Design, Implementation, and Practical Example

This article explains the Chain of Responsibility design pattern, demonstrates its use for request validation and processing in Java backend applications, provides complete code examples—including abstract handler, concrete validators, business logic, and a test harness—while discussing its advantages, drawbacks, and real‑world analogues such as servlet filters.

Top Architect
Top Architect
Top Architect
Chain of Responsibility Pattern in Java: Design, Implementation, and Practical Example

The author introduces a common problem where multiple validation steps are duplicated across similar methods, leading to code repetition, heavy pre‑logic sections, and difficulty maintaining execution order. To address these issues, the Chain of Responsibility pattern is proposed.

Definition : The pattern treats each node in a chain as an object that can handle a request or pass it to the next node, decoupling request senders from handlers. It is a behavioral design pattern often used in approval workflows.

UML Class Diagram (illustrated in the original article) shows an abstract Handler<T> with a reference to the next handler and a nested Builder<T> for constructing the chain.

public abstract class Handler<T> {
    protected Handler next;
    private void next(Handler next) {
        this.next = next;
    }
    public abstract void doHandler(Member member);
    public static class Builder<T> {
        private Handler<T> head;
        private Handler<T> tail;
        public Builder<T> addHandler(Handler handler) {
            if (this.head == null) {
                this.head = this.tail = handler;
                return this;
            }
            this.tail.next(handler);
            this.tail = handler;
            return this;
        }
        public Handler<T> build() {
            return this.head;
        }
    }
}

Concrete handlers are then defined:

public class ValidateHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (StringUtils.isEmpty(member.getUsername()) || StringUtils.isEmpty(member.getPassword())) {
            System.out.println("用户名和密码不能为空");
            return;
        }
        if (null != next) {
            next.doHandler(member);
        }
    }
}
public class LoginHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (!"jack".equals(member.getUsername()) || !"666".equals(member.getPassword())) {
            System.out.println("用户名密码不正确");
            return;
        }
        if (null != next) {
            next.doHandler(member);
        }
    }
}
public class AuthHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (!"管理员".equals(member.getRoleName())) {
            System.out.println("您不是管理员,没有操作权限");
            return;
        }
        if (null != next) {
            next.doHandler(member);
        }
    }
}
public class BusinessLogicHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        System.out.println("执行业务逻辑。。");
    }
}

A test class builds the chain and runs a sample member through the validators:

public class Test {
    public static void main(String[] args) {
        Handler.Builder builder = new Handler.Builder();
        builder.addHandler(new ValidateHandler())
               .addHandler(new LoginHandler())
               .addHandler(new AuthHandler())
               .addHandler(new BusinessLogicHandler());
        Member member = new Member();
        member.setUsername("");
        member.setPassword("");
        builder.build().doHandler(member);
    }
}

The article also relates the pattern to the J2EE Filter interface, showing that a servlet filter chain is a concrete example of a responsibility chain.

public interface Filter {
    public default void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
    public default void destroy() {}
}
public class MockFilterChain implements FilterChain {
    @Nullable private ServletRequest request;
    @Nullable private ServletResponse response;
    private final List
filters;
    @Nullable private Iterator
iterator;
    public MockFilterChain() { this.filters = Collections.emptyList(); }
    public MockFilterChain(Servlet servlet) { this.filters = initFilterList(servlet); }
    public MockFilterChain(Servlet servlet, Filter... filters) {
        Assert.notNull(filters, "filters cannot be null");
        Assert.noNullElements(filters, "filters cannot contain null values");
        this.filters = initFilterList(servlet, filters);
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        Assert.notNull(request, "Request must not be null");
        Assert.notNull(response, "Response must not be null");
        if (this.iterator == null) { this.iterator = this.filters.iterator(); }
        if (this.iterator.hasNext()) {
            Filter nextFilter = this.iterator.next();
            nextFilter.doFilter(request, response, this);
        }
        this.request = request;
        this.response = response;
    }
    public void reset() { this.request = null; this.response = null; this.iterator = null; }
}

Finally, the article lists the pattern’s pros (decoupling, flexible chain, easy extension) and cons (potential performance impact, risk of circular references), and encourages readers to experiment and discuss further.

backendChain of ResponsibilityJavasoftware architecturevalidationdesign patternfilter
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

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