Skip to content

Sequential Request Processing

Pass a request along a chain until one handler takes it

Builds on OCP - The Open/Closed Principle

Stage 3core2 min read

The current design sends every customer support request through one big class. Fixed if-else blocks decide which department handles a ticket. This ties the parts tightly together (tight coupling). It is hard to maintain, hard to test, and you cannot reorder the handlers while the program runs.


1. Understanding the Issue

In an online shop's support system, tickets come in many kinds, such as general questions, billing refunds, technical bugs and shipping problems.

The logic for each team is not kept apart. The SupportService class checks the ticket type and runs all the handling steps inside one method. So one central dispatcher must know the inner details of every support department.


2. Issues in the Above Code

IssueDescription
Violation of the Open-Closed PrincipleEach time you add a new request type (e.g., fraud investigation or VIP escalation), you must edit the handleRequest method. This breaks the Open-Closed Principle: a class should be open for extension but closed for modification.
Monolithic CodeAll logic sits in one method, so it is hard to maintain, test and extend. The support teams are tied together inside one shared block of if-else.
Scalability and Flexibility BottlenecksAs more teams are added, you cannot change the order of checks or insert a new filter without editing the core class. Adding handlers or changing priorities becomes awkward.

3. Structural Deficiencies

  • Rigid Execution Order: The order of checks is fixed when the code is compiled, by the order of the if-else statements. You cannot rearrange, switch off or prioritize handlers from settings at runtime.
  • Untestable Units: You cannot unit test one department alone. To test billing, you must go through the central SupportService class.
  • String-Literal Fragility: Routing depends only on magic strings (plain text values, e.g., "general", "refund"). A typo is not caught when you compile. It shows up only when the program runs.

4. Summary of the "Smell"

When a fixed run of conditional branches decides who should handle what, the code becomes one rigid block.

The Chain of Responsibility Pattern fixes this. Each department becomes its own handler object, and the handlers are linked into a chain. Each handler either processes the request or passes it on. The sender no longer depends on the receivers, and you can add or reorder handlers while the program runs.

In this topic

Before code1 file

Before/Main.java56 linesGitHub
package DesignPatterns.BehaviouralPatterns.ChainOfResponsibilityPattern.Before;import java.util.*;/** * PROBLEM: Monolithic Gating & Tight Coupling. * The 'SupportService' class handles every single department's triage logic directly. * It is tightly coupled to every ticket type and contains all execution handling in one place. */class SupportService {    /**     * ISSUE 1: VIOLATION OF OPEN/CLOSED PRINCIPLE (OCP)     * Adding a new department (e.g., "escalations" or "fraud") requires modifying      * this exact method, introducing regression risks for existing working logic.     *      * ISSUE 2: MAGIC STRINGS & RIGID CONDITIONALS     * Comparisons rely on string literals ("general", "refund").     *      * ISSUE 3: STATIC / IMMUTABLE EXECUTION ORDER     * The evaluation order is hardcoded into the if-else sequence. You cannot dynamically      * reorder handlers at runtime (e.g., placing Fraud before Billing) without      * rewriting the class structure.     */    public void handleRequest(String type) {        if (type.equals("general")) {            // General support logic hardcoded here            System.out.println("Handled by General Support"); //        } else if (type.equals("refund")) {            // Billing team logic hardcoded here            System.out.println("Handled by Billing Team"); //        } else if (type.equals("technical")) {            // Tech support logic hardcoded here            System.out.println("Handled by Technical Support"); //        } else if (type.equals("delivery")) {            // Delivery team logic hardcoded here            System.out.println("Handled by Delivery Team"); //        } else {            // Fallback default            System.out.println("No handler available"); //        }    }}public class Main {    public static void main(String[] args) {        SupportService supportService = new SupportService(); //                // Simulating incoming requests        supportService.handleRequest("general"); //        supportService.handleRequest("refund"); //        supportService.handleRequest("technical"); //        supportService.handleRequest("delivery"); //        supportService.handleRequest("unknown"); //    }}

Done with this topic?

How well do you know it?

PreviousIterator Pattern: Sequential Access Without Exposure