Chain of Responsibility Design Pattern ✨😎

An overview of the Chain of Responsibility design pattern & its implementation with a real-world scenario!

Irushinie Muthunayake
Geek Culture

--

📍 Chain of Responsibility Design Pattern is a Behavioral design pattern.

📍 The chain of responsibility pattern is mostly used to pass the responsibility to the next if the current object cannot handle it at the moment. By utilizing this Chain of Responsibility Design Pattern, you can accomplish the loose coupling.

Let’s understand this design pattern with the below example:

Assume that you need to control a menu on the user level. There you have the CEO, Director, Manager, and the Executives. So accordingly each of them has multiple levels of permissions. So if you need to implement something based on these particular levels of permission, you could use this design pattern.

The best example for the chain of a responsibility design pattern that is implemented at the practical level is the Java API logger.

Output:

INFO: this is info
WARNING: this is warning
SEVERE: this is severe

So accordingly you can see that this goes on a hierarchical level. (Note: if not find a handler for a particular level, it just ignore that)

When to use Chain of Responsibility? 🙄

🔥 We can use the Chain of Responsibility design pattern when our program is looking for a process in different types of requests in various approaches, but the exact kind of requests & the sequences of them are unspecified beforehand.

🔥 Can use this pattern if want to change the set of handlers & their order at runtime.

🔥 We can use this pattern when we want to execute some handlers in a certain order.

The most important fact here is, this design pattern encourages loosely coupled.

Example: The sender doesn't know who the receiver is and the receiver doesn't know who the sender is. Also, the sender can perform their job without knowing who will receive the message and at the same time, the receiver can perform their job without knowing the sender. So that means we can decouple the sender and the receiver by using this design pattern.

Class diagram of the Chain of Responsibility design pattern

Ref:https://dzone.com/articles/using-chain-of-responsibility-design-pattern-in-ja

Sequence diagram of the Chain of Responsibility design pattern

The beauty of this design pattern is you can change the order of the receivers and senders without even touching the core implementation of the program

Let’s move to a real-world scenario understand this design pattern:

💥Scenario

“Lipsy” is a women’s clothing store in Kandy and they have given some kinds of discounts to their customers as christmas offers. Each of these offers has a special name and that amount is deducted from the bill when buying clothes.

✹ Golden discount— 5% off (up to 500/=)
✹ AweOffers discount— 5% off (500/= to 1500/=) & will get the Golden discount
✹ DealDive discount— 5% off (1500/= to 2500/=)& will get the Golden, AweOffers discount too
✹ Marvell discount— 5% off (2500/= to 5000/=)& will get the Golden, AweOffers, DealDive discount too
✹ HappyDaisy discount— 5% off(above 5000/=)& will get the Golden, AweOffers, DealDive, Marvell discount

So below table is some expected outputs that should become:

Let’s move to the implementation of this scenario:

✨ DiscountHandler class

This is an abstract class( you can use an interface here if needed). And this class defines handling the requests.

✨ Bill class

✨ Golden class

This class extends the “DiscountHandler class”. In line 6, it calculates the discount amount.

“if(bill.getTotalAmount()<=500)” in line number 8 refers to checking whether the bill amount is less than or equal to 500 rupees.

“return bill.getDiscount()” in line number 9 refers to returning the value as there is no need to calculate any other amount of discounts.

“return successor.applyDiscount(bill)” in line number 12 is actually the place where the real chain happens. Here, what happens is, if the “if ” condition is not true then it passes this to the successor to calculate other discounts.

✨ AweOffers class

This class also extends the “DiscountHandler” class. (And I have implemented the DealDive, Marvell, and HappyDaisy classes same as this. You can see the full source code in the GitHub repository)

✨ Discount class

Here there’s no logic inside this class. Just passing the value to the successor.

✨ Application class

“Golden golden = new Golden()” in line number 5 refers to creating an object from Golden. And then I have created the objects for all other discounts as well(lines 6 to 9).

In line 10 (Discount discount = new Discount()), I have created a class called Discount and there is no logic inside that class (this was created in a case where you need to change the name of “Discount” in the future so you need to keep this name outside the real logic) and I have used that class at the beginning of the chain.

As the Discount is the lowest level, I have started the chain from discount (you could see that from line 12)

Output:

Click on the below link to see the full source code for this scenario:

Advantages and Disadvantages of Chain of Responsibility Design Pattern

Advantages:

🌱 This design pattern helps to decouple the sender of the request and the receiver.

🌱 This pattern enhances the flexibility in allocating responsibilities to particular objects or changing the order of the chain.

🌱 The chain of responsibility design pattern provides the ability for a group of classes to act as one.

Disadvantages:

🌱 Sometimes it will be difficult to observe the run-time characteristics and remove errors.

🌱 Sometimes, this Chain of Responsibility design pattern can get broken easily.

(Example:

✹ The request can get dropped if a handler was unsuccessful to call the next handler.

✹ If one handler calls the incorrect handler, it can harm the chain)

🌱 This design pattern can increase the maintenance sometimes, because of the occurring of duplicate code across handlers.

--

--