Search code examples
javaoopdesign-patternschain-of-responsibility

Is the Chain of Responsibility pattern a good replacement for a sequence of conditions?


When you need to execute a sequence of actions in a particular order, is the Chain of Responsibility pattern a good replacement for a sequence of conditions? Is it a good idea to replace a simple method with conditions like this:

public class MyListener implements MyHttpListener {

    // if false, the request will be thrown away and subsequent listeners will not be notified
    @Override
    public boolean onHttpRequestSend(HttpMessage msg) { 
        // handlers can change msg

        boolean isA = handleA(msg);
        if (isA) return false;

        boolean isB_notA = handleB(msg);
        if (isB_notA) return false;

        boolean isC_notA_notB = handleC(msg);
        if (isC_notA_notB) return true;

        ...

        throw new IllegalStateException();
    }
}

Now replace it with an implementation of the Chain of Responsibility pattern:

public class MyListener implements MyHttpListener {
    @Override
    public boolean onHttpRequestSend(HttpMessage msg) {
        ProcessingStep first = new StepA()
        ProcessingResult result = first.process(new ProcessingResult(msg, true));
        return result.returnValue;
    }
}

public interface ProcessingStep {
    ProcessingResult process(ProcessingResult stepResult);
}

public class ProcessingResult {
    HttpMessage message;
    boolean returnValue;
}

public class StepA implements ProcessingStep {
    @Override
    public ProcessingResult process(ProcessingResult stepResult) {
        if (handleA()) {
            return stepResult;
        }
        else {
            return new StepB().process(stepResult);
        }
    }
}   
public class StepB implements ProcessingStep {
    @Override
    public ProcessingResult process(ProcessingResult stepResult) {
        return stepResult; // this is the last step
    }
}

Solution

  • The Chain of Responsibility is meant for the exact scenario that you are describing, i.e., replacing a chain of if ... else with one call that handles your request (wrapped in the msg in your example).

    So the answer is: Yes, your second code is a good replacement of your first code.


    Whether you should replace your first piece of code with the second one is another question. For a code as simple as the one you currently have, adding a Design Pattern may be an overkill. The supplementary reasons for using this pattern are:

    • Dynamic arrangement of the if ... else blocks;
    • Adding new processing blocks;
    • Repurposing the handlers as dispatchers, capable of sending out the msgin a variety of directions, forming a Tree of Responsibility.

    • If your situation seems like it demands a Design Pattern, go ahead.
    • If it doesn't, leave it.
    • If you are in doubt, add the pattern for now. If in future you see you/your teammates getting confused about your code, remove it at that time.