Fundamentals 13 min read

Mastering the Chain of Responsibility: From SOLID Principles to Spring Integration

This article explains the seven SOLID design principles, introduces the Chain of Responsibility pattern, demonstrates its application to a video‑review workflow with step‑by‑step Java code, and shows how to evolve the implementation from a basic chain to a Spring‑managed, fully open‑closed solution.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Mastering the Chain of Responsibility: From SOLID Principles to Spring Integration

SOLID Principles (brief)

The Open‑Closed, Single Responsibility, Liskov Substitution, Dependency Inversion, Interface Segregation, Composite/Aggregate Reuse and Least Knowledge principles guide the design of extensible, maintainable code.

Chain of Responsibility (CoR) Pattern

CoR is a behavioral pattern that decouples a request sender from multiple potential handlers by linking handlers in a linear chain. A request traverses the chain until a handler processes it, allowing handlers to be added or removed without changing the sender.

Business Scenario: Video Review & Publication

A video passes through upload, transcoding, review and publishing stages. The review stage requires different processing logic depending on the upload source (e.g., "Fox Friend", "News", "Special Author"). The original code used a long series of nested if‑else statements, violating the Open‑Closed principle and making extensions error‑prone.

Step 1 – Basic CoR Implementation

public interface Handler {
    void handle(Object videoInfo);
    void setNext(Handler handler);
}

public class Handler1 implements Handler {
    private Handler next;
    @Override
    public void handle(Object videoInfo) {
        System.out.println("handler1处理");
        if (next != null) next.handle(videoInfo);
    }
    @Override
    public void setNext(Handler handler) { this.next = handler; }
}

public class Handler2 implements Handler { /* similar */ }
public class Handler3 implements Handler { /* similar */ }

public class Client {
    public static void main(String[] args) {
        Handler h1 = new Handler1();
        Handler h2 = new Handler2();
        Handler h3 = new Handler3();
        h1.setNext(h2);
        h2.setNext(h3);
        h1.handle("videoInfo");
    }
}

This version works but each handler still holds a reference to the next handler, which breaches the Single Responsibility principle and forces the client to manage the chain.

Step 2 – Introducing a Chain Manager

public class HandlerChain {
    private List<Handler> list = new ArrayList<>();
    public void add(Handler handler) { list.add(handler); }
    public void handle(Object videoInfo) { list.forEach(h -> h.handle(videoInfo)); }
}

The client now only adds handlers to HandlerChain and invokes handle. The chain manager removes the need for each handler to store a next reference, reducing coupling. However, adding a new handler still requires modifying the manager.

Step 3 – Full Open‑Closed Solution with Spring

By declaring each handler as a Spring @Component and injecting the list of all Handler beans into the chain manager, the system becomes truly open‑closed: new handlers are discovered automatically without source changes.

@Component
public class Handler1 implements Handler {
    @Override
    public void handle(Object videoInfo) {
        if (videoInfo.toString().contains("handler1")) {
            System.out.println("handler1处理");
        }
    }
}

@Component
public class Handler2 implements Handler {
    @Override
    public void handle(Object videoInfo) {
        System.out.println("handler2处理");
    }
}

@Component
public class Handler3 implements Handler {
    @Override
    public void handle(Object videoInfo) {
        System.out.println("handler3处理");
    }
}

@Component
public class HandlerChain {
    @Autowired
    private List<Handler> list;
    public void handle(Object videoInfo) { list.forEach(h -> h.handle(videoInfo)); }
}

@Component
public class Client {
    @Autowired
    private HandlerChain handlerChain;
    public void handle(Object videoInfo) { handlerChain.handle(videoInfo); }
}

Adding a new processing step now only requires creating a new Handler implementation and annotating it with @Component. The Spring IoC container wires it into the chain automatically, satisfying Open‑Closed, Single Responsibility and Dependency Inversion principles.

Key Takeaways

Replace large if‑else blocks with a CoR to decouple request routing from processing logic.

Extract chain orchestration into a dedicated manager to avoid each handler holding a reference to the next one.

Leverage Spring’s IoC container to achieve true open‑closed behavior: new handlers are added without modifying existing code.

The resulting architecture is easier to maintain, extend, and less prone to bugs introduced by manual chain manipulation.

CoR diagram
CoR diagram
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 PatternsJavaspringdependency-injectionSOLID
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

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.