Eliminating if‑else Branches with Strategy Pattern, Map, and Chain of Responsibility in Java

This article demonstrates how to replace cumbersome if‑else or switch statements in Java backend receipt processing by applying the Strategy pattern with a Map dictionary, a simple factory, and the Chain of Responsibility pattern, while also showing reflective class loading for extensibility.

Top Architect
Top Architect
Top Architect
Eliminating if‑else Branches with Strategy Pattern, Map, and Chain of Responsibility in Java

In logistics systems, each EDI XML message is followed by a receipt indicating its processing status, and handling many receipt types (e.g., MT1101, MT2101, MT4101, MT8104, MT9999) with traditional if‑else branches quickly violates the Open‑Closed Principle.

@Data
public class Receipt {
    /**
     * 回执信息
     */
    String message;
    /**
     * 回执类型(`MT1101、MT2101、MT4101、MT8104、MT9999`)
     */
    String type;
}

A builder generates a list of sample receipts:

public class ReceiptBuilder {
    public static List<Receipt> generateReceiptList() {
        List<Receipt> receiptList = new ArrayList<>();
        receiptList.add(new Receipt("我是MT2101回执喔", "MT2101"));
        receiptList.add(new Receipt("我是MT1101回执喔", "MT1101"));
        receiptList.add(new Receipt("我是MT8104回执喔", "MT8104"));
        receiptList.add(new Receipt("我是MT9999回执喔", "MT9999"));
        return receiptList;
    }
}

Using a naïve if‑else approach leads to a long chain of conditional blocks, making the code hard to maintain as new receipt types appear.

Applying the Strategy pattern, we define a common interface and concrete strategies for each receipt type, then use a simple factory (or a Map) to obtain the appropriate strategy at runtime:

public interface IReceiptHandleStrategy {
    void handleReceipt(Receipt receipt);
}

Concrete strategies such as Mt2101ReceiptHandleStrategy implement the interface and contain the specific handling logic. The factory stores the mapping in a Map<String, IReceiptHandleStrategy> so adding a new type only requires inserting a new entry.

To further decouple the client from the factory, the Chain of Responsibility pattern is introduced. An IReceiptHandler interface defines handleReceipt(Receipt receipt, IReceiptHandleChain chain), and a ReceiptHandleChain iterates over a list of handlers until one processes the receipt.

public interface IReceiptHandler {
    void handleReceipt(Receipt receipt, IReceiptHandleChain handleChain);
}

The handler list can be populated automatically via reflection. The ReflectionUtil class scans a given package, loads all classes implementing IReceiptHandler, and returns them as a set:

public class ReflectionUtil {
    private static final Set<Class<?>> CLASS_SET;
    static {
        CLASS_SET = getClassSet("com.yaolong");
    }
    // ... methods for class loading and package scanning ...
    public static Set<Class<?>> getClassSetBySuper(Class<?> superClass) {
        Set<Class<?>> classSet = new HashSet<>();
        for (Class<?> cls : CLASS_SET) {
            if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
                classSet.add(cls);
            }
        }
        return classSet;
    }
}

The ReceiptHandlerContainer uses this utility to build the handler list dynamically, ensuring that adding a new handler class (e.g., Mt6666ReceiptHandler) requires no changes to existing code.

Finally, the article concludes that while simple if‑else may suffice for a few branches, employing design patterns such as Strategy, Simple Factory, and Chain of Responsibility greatly improves code readability, maintainability, and adherence to the Open‑Closed Principle for complex business logic.

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.

BackendChain of ResponsibilityDesign PatternsJavaStrategy Pattern
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

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.