Refactoring C2B Valuation Logic with the Chain of Responsibility Pattern

This article explains how the Chain of Responsibility design pattern was introduced to redesign a C2B valuation service, improving code maintainability, extensibility, and performance through modular handlers, dynamic chain assembly, and practical examples in Java.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
Refactoring C2B Valuation Logic with the Chain of Responsibility Pattern

The article introduces the online C2B recycling business of ZhaiZhai, which provides precise price estimates for 3C digital products as the first step in the valuation workflow.

Early issues included rough code, rapid product changes, complex business logic, and performance bottlenecks, prompting a redesign of the valuation module.

It then explains the Chain of Responsibility pattern, describing its definition, advantages (single responsibility, open‑closed principle) and disadvantages (long chain, slower debugging).

Typical valuation flow is shown as a chain structure where each module has a single responsibility.

Implementation starts with defining an abstract handler interface and concrete handlers, illustrated with Java code examples:

public interface ValuationResponsibilityChainHandle<ChainResponsibilityContext, ChainResponsibilityRequest, ChainResponsibilityResponse> {
    void handle(ChainResponsibilityContext context, ChainResponsibilityRequest request, ChainResponsibilityResponse response);
    void setNextHandler(ValuationResponsibilityChainHandle<ChainResponsibilityContext, ChainResponsibilityRequest, ChainResponsibilityResponse> nextHandle);
    ValuationResponsibilityChainHandle<ChainResponsibilityContext, ChainResponsibilityRequest, ChainResponsibilityResponse> getNextHandler();
}

A sample BlacklistHandler demonstrates how a concrete handler performs blacklist validation and forwards the request.

public class BlacklistHandler extends AbstractValuationChainValuationResponsibilityHandle<ValuationContext, ValuationRequest, BmDealPriceDto> {
    @Autowired
    private ValuationApolloService valuationApolloService;
    @Override
    public void handle(ValuationContext context, ValuationRequest request, BmDealPriceDto bmDealPriceDto) {
        log.info("精准估价-黑名单校验, context={}, bmDealPriceDto={}", context, bmDealPriceDto);
        if (Objects.isNull(request.getUid())) { return; }
        if (!valuationApolloService.getBmValuationBlackList().contains(request.getUid())) { return; }
        context.setSkipNode(true);
        this.invokeNext(context, chainResponsibilityRequest, chainResponsibilityResponse);
    }
    @Override
    public void setNextHandler(ValuationResponsibilityChainHandle<ChainResponsibilityContext, ChainResponsibilityRequest, ChainResponsibilityResponse> nextHandler) {
        this.nextHandler = nextHandler;
    }
}

To support dynamic chain assembly, a Builder class creates a list of handlers based on business scenario keys, and the chain is executed by iterating over the list.

public List<AbstractValuationChainValuationResponsibilityHandle> buildChain(Integer type) {
    List<AbstractValuationChainValuationResponsibilityHandle> chain = Lists.newArrayList();
    switch (type) {
        case BuildChainConstant.SCENE_A:
            buildSceneA(chain);
            break;
        default:
            break;
    }
    return chain;
}

The article also shows how to control flow interruption by adding a skipNode method to handlers, allowing conditional execution based on context.

public interface ValuationResponsibilityChainHandle<ChainResponsibilityContext, ChainResponsibilityRequest, ChainResponsibilityResponse> {
    void handle(ChainResponsibilityContext context, ChainResponsibilityRequest request, ChainResponsibilityResponse response);
    boolean skipNode(ChainResponsibilityContext context, ChainResponsibilityRequest request, ChainResponsibilityResponse response);
}

Finally, it discusses broader applications of the pattern, such as Netty’s inbound/outbound channel handlers, Spring Security, Spring AOP, MyBatis plugins, and Dubbo filters, and provides performance‑related advice (push, split, reduce, pressure‑test, monitor, guard).

The article concludes that using the Chain of Responsibility pattern reduces code complexity, improves robustness, and helps developers handle rapidly evolving business requirements.

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 ResponsibilityJava
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

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.