🤖📘🍻 Hooray! After 3 years of work, we've finally released a new ebook on design patterns! Check it out »

Chain of Responsibility Design Pattern in Java: Before and after

Before

The client is responsible for stepping through the "list" of Handler objects, and determining when the request has been handled.

class Handler {
    private static final Random RANDOM = new Random();
    private static int nextID = 1;
    private int id = nextID++;

    public boolean execute(int num) {
        if (RANDOM.nextInt(4) != 0) {
            System.out.println("   " + id + "-busy  ");
            return false;
        }
        System.out.println(id + "-handled-" + num);
        return true;
    }
}

public class ChainDemo {
    public static void main(String[] args) {
        Handler[] nodes = {new Handler(), new Handler(),
                new Handler(), new Handler()};
        for (int i = 1, j; i < 6; i++) {
            System.out.println("Operation #" + i + ":");
            j = 0;
            while (!nodes[j].execute(i)) {
                j = (j + 1) % nodes.length;
            }
            System.out.println();
        }
    }
}

Output

Operation #1:
   1-busy
   2-busy
   3-busy
4-handled-1

Operation #2:
   1-busy
   2-busy
   3-busy
   4-busy
1-handled-2

Operation #3:
   1-busy
   2-busy
   3-busy
   4-busy
   1-busy
2-handled-3

Operation #4:
   1-busy
   2-busy
   3-busy
4-handled-4

Operation #5:
   1-busy
2-handled-5


After

The client submits each request to the "chain" abstraction and is decoupled from all subsequent processing.

class Handler {
    private final static Random RANDOM = new Random();
    private static int nextID = 1;
    private int id = nextID++;
    private Handler nextInChain;

    public void add(Handler next) {
        if (nextInChain == null) {
            nextInChain = next;
        } else {
            nextInChain.add(next);
        }
    }

    public void wrapAround(Handler root) {
        if (nextInChain == null) {
            nextInChain = root;
        } else {
            nextInChain.wrapAround(root);
        }
    }

    public void execute(int num) {
        if (RANDOM.nextInt(4) != 0) {
            System.out.println("   " + id + "-busy  ");
            nextInChain.execute(num);
        } else {
            System.out.println(id + "-handled-" + num);
        }
    }
}

public class ChainDemo {
    public static void main(String[] args) {
        Handler rootChain = new Handler();
        rootChain.add(new Handler());
        rootChain.add(new Handler());
        rootChain.add(new Handler());
        rootChain.wrapAround(rootChain);
        for (int i = 1; i < 6; i++) {
            System.out.println("Operation #" + i + ":");
            rootChain.execute(i);
            System.out.println();
        }
    }
}

Output

Operation #1:
   1-busy  
   2-busy  
   3-busy  
4-handled-1

Operation #2:
   1-busy  
   2-busy  
   3-busy  
   4-busy  
1-handled-2

Operation #3:
   1-busy  
   2-busy  
3-handled-3

Operation #4:
   1-busy  
   2-busy  
3-handled-4

Operation #5:
1-handled-5

Code examples

More info, diagrams and examples of the Chain of Responsibility design pattern you can find on our new resource Refactoring.Guru.