Tutorials  /  JavaScript

Java Design Patterns: Understanding the Functionality of the Chain of Responsibility Pattern

Ccentron Redaktion · October 2024 ·4 min read ·JavaScript, Tutorial

Learn how the Chain of Responsibility design pattern in Java enables efficient and decoupled request processing. From the basics to practical implementation using an ATM dispenser system - discover how this pattern improves code organization. Dive into the world of behavioral patterns and optimize your software architecture with this comprehensive overview.

Example of the Chain of Responsibility Pattern in the JDK

An example of the Chain of Responsibility pattern in the JDK is the try-catch block code, where multiple catch blocks exist, each processing a specific exception. When an exception occurs in the try block, it is sent to the first catch block for processing. If the catch block cannot process it, it forwards the request to the next object in the chain, the next catch block. If the last catch block also cannot process it, the exception is passed outside the chain to the calling program.

VM

Matching infrastructure at centron

Node applications need somewhere to run: ccloud³ VMs with full root access from €3.12 per month – or as a managed server if you would rather not run it yourself. Rent a cloud server →

Example of the Chain of Responsibility Design Pattern

A great example of the Chain of Responsibility pattern is the ATM. The user enters the amount to be dispensed, and the ATM dispenses the amount in defined currency notes such as $50, $20, $10, etc. If the user enters an amount that is not divisible by 10, an error is reported. We will use the Chain of Responsibility pattern to implement this solution. The chain will process the request in the same order as shown in the diagram below. Note that we could implement this solution easily in a single program, but then the complexity would increase, and the solution would be tightly coupled. Therefore, we create a chain of dispensing systems to issue $50, $20, and $10 notes.

Base Classes and Interface for the Chain of Responsibility Design Pattern

We can create a Currency class that stores the amount to be dispensed and is used by the chain implementations. The base interface should have a method to define the next processor in the chain and the method that processes the request. Our ATM dispenser interface looks as follows.

Go
package com.journaldev.design.chainofresponsibility;

public class Currency {
    private int amount;
    
    public Currency(int amt){
        this.amount=amt;
    }
    
    public int getAmount(){
        return this.amount;
    }
}
Go
package com.journaldev.design.chainofresponsibility;

public interface DispenseChain {
    void setNextChain(DispenseChain nextChain);
    void dispense(Currency cur);
}

Chain Implementations of the Chain of Responsibility Pattern

Various processor classes need to be created that implement the DispenseChain interface and provide the implementation of the dispense methods. As we develop our system to work with three types of currency notes - $50, $20, and $10 - we will create three concrete implementations.

Go
package com.journaldev.design.chainofresponsibility;

public class Dollar50Dispenser implements DispenseChain {
    private DispenseChain chain;
    
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }

    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount() >= 50){
            int num = cur.getAmount()/50;
            int remainder = cur.getAmount() % 50;
            System.out.println("Dispensing "+num+" 50$ note");
            if(remainder !=0) this.chain.dispense(new Currency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
}
Go
package com.journaldev.design.chainofresponsibility;

public class Dollar20Dispenser implements DispenseChain{
    private DispenseChain chain;
    
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }

    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount() >= 20){
            int num = cur.getAmount()/20;
            int remainder = cur.getAmount() % 20;
            System.out.println("Dispensing "+num+" 20$ note");
            if(remainder !=0) this.chain.dispense(new Currency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
}
Go
package com.journaldev.design.chainofresponsibility;

public class Dollar10Dispenser implements DispenseChain {
    private DispenseChain chain;
    
    @Override
    public void setNextChain(DispenseChain nextChain) {
        this.chain=nextChain;
    }

    @Override
    public void dispense(Currency cur) {
        if(cur.getAmount() >= 10){
            int num = cur.getAmount()/10;
            int remainder = cur.getAmount() % 10;
            System.out.println("Dispensing "+num+" 10$ note");
            if(remainder !=0) this.chain.dispense(new Currency(remainder));
        }else{
            this.chain.dispense(cur);
        }
    }
}

Creating the Chain for the Chain of Responsibility Design Pattern

This is a very important step, and we should create the chain carefully; otherwise, a processor may not receive any requests at all.

Go
package com.journaldev.design.chainofresponsibility;

import java.util.Scanner;

public class ATMDispenseChain {
    private DispenseChain c1;

    public ATMDispenseChain() {
        // initialize the chain
        this.c1 = new Dollar50Dispenser();
        DispenseChain c2 = new Dollar20Dispenser();
        DispenseChain c3 = new Dollar10Dispenser();

        // set the chain of responsibility
        c1.setNextChain(c2);
        c2.setNextChain(c3);
    }

    public static void main(String[] args) {
        ATMDispenseChain atmDispenser = new ATMDispenseChain();
        while (true) {
            int amount = 0;
            System.out.println("Enter amount to dispense");
            Scanner input = new Scanner(System.in);
            amount = input.nextInt();
            if (amount % 10 != 0) {
                System.out.println("Amount should be in multiple of 10s.");
                return;
            }
            // process the request
            atmDispenser.c1.dispense(new Currency(amount));
        }
    }
}

Key Points of the Chain of Responsibility Design Pattern

  • The client does not know which part of the chain processes the request, and it sends the request to the first object in the chain.
  • Each object in the chain has its own implementation for processing the request, either completely or partially, or to forward it to the next object in the chain.
  • Each object in the chain should have a reference to the next object in the chain to forward the request.

Examples of the Chain of Responsibility Pattern in the JDK

  • java.util.logging.Logger#log()
  • javax.servlet.Filter#doFilter()

That was all about the Chain of Responsibility design pattern. I hope you enjoyed it and it helped clarify your understanding of this design pattern.

Jetzt 200 € Guthaben sichern

Testen Sie Ihr Setup auf ccloud³

Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.

centron Redaktion Technische Redaktion

Das Redaktionsteam von centron schreibt Anleitungen aus dem Betriebsalltag: getestet auf unserer eigenen Plattform, betrieben im Rechenzentrum in Hallstadt bei Bamberg.

Kategorie JavaScript
Teilen
Noch offene Fragen?

Unser Team hilft Ihnen bei Ihrem konkreten Setup weiter – von Menschen, die die Plattform selbst betreiben.

War dieses Tutorial hilfreich?

Ihre Antwort wird anonym gespeichert und hilft uns, die Tutorials zu verbessern.

Kommentare

Noch keine Kommentare – stellen Sie die erste Frage zu diesem Tutorial.

Zum Kommentieren anmelden

Kommentare stehen centron-Kunden offen. Melden Sie sich in Ihrem Konto an, um eine Frage zu diesem Tutorial zu stellen.

Weiterlesen

Das könnte Sie auch interessieren

Jetzt kostenlos anfangen

Melden Sie sich an und erhalten Sie in den ersten 60 Tagen ein Guthaben von 200 € bei centron.

Dieses Werbeangebot gilt nur für neue Konten. Angebot ausschließlich für Gewerbetreibende.

Jetzt loslegen Sales kontaktieren