Chain Of Responsibility Design Pattern

--

As you already know this is another design pattern article. So welcome to the chain of responsibility design pattern. I have published four articles regarding design patterns and all of those four are under the creational type. So if you are new to design patterns, you can always refer to my previous articles.

Today let’s learn the chain of responsibility design pattern which is under behavioral type. Java API logger is an example of the chain of responsibility design pattern.

The chain of responsibility pattern creates a chain of receiver objects for a request. This pattern decouples the sender and receiver of a request based on the type of request. Each receiver contains a reference to another receiver. If one particular object cannot handle the request, then it will pass the same request to the next receiver and so on. In other cases loosely coupled sender(client) doesn’t know who is the receiver(concrete Handler) as well as the receiver doesn’t know who is the sender.

Let’s get a real-world example to understand this design pattern. Let’s say you are implementing a system for ATM machines. In an ATM machine, we can withdraw money which is in our bank account. So let’s there is a person called Saman. Saman needs to withdraw 3700 (Lankan rupees). The process is like below;

  1. First, he inserts his debit card
  2. enters the secret code
  3. selects the withdraw option
  4. enters the amount

The moment he enters the amount ATM machine goes through some process. First, it checks whether the person's account balance is greater than the requested withdrawal amount. Then it will check how many notes it should issue. For example, for 3700 SL rupees ATM machine will issue 3 Thousand notes, 1 five hundred notes, and 2 hundred notes. So how do ATM machines handle this? Let’s implement the scenario.

Before the implementation there are some edge cases like ATM machine should contain more notes when issuing those notes. As an example in real world when we get the same above example if the ATM machine does not contain 1000 notes it will issue the 3000 rupees from six 500 notes. Or may be if it contains one 1000 note then it issued one 1000 note and four 500 notes. Since this is an example implementation I will not consider like those edge cases.

So first let’s create the Handler class. Handler class contains Handler type attribute which is called successor. Also, we have set a successor method and an abstract method called Withdraw as given below.

Then you need to implement the Bank Account class as given below. We have four attributes. Then you need to implement the constructor. Constructor only contains accountNumber and requestAmount parameters. After that, you need to implement getters and setters like in the below.

Next, we need to create Hundred, FiveHundred, Thousand and FiveThousand handler classes and you need to extend all those classes from the Handler class. Since all those classes are extended from the handler class you need to override the withdraw method and have to implement the logic separately for each class like in the below. So in FivethousandHandler, it will only handle if the requested withdrawal amount is more than 5000. Then it checks how many 5000 notes FivethousandHandler should be issued. After it issued 5000 notes it checks if the requested amount contains any remaining amount so if it contains any value it passes the remaining amount to the Thousand Handler.

Then is ThosuandHandler it will only handle notes when the requested withdrawal amount is more than 1000. Then it will check how many 1000 notes should be issued. After it issued 1000 notes it checks if the requested amount contains any remaining amount so if it contains any value, it passes the remaining amount to the FiveHundredHandler. Likewise you need to implement the FiveHundredHandler and HundredHandler.

Finally, inside the main program, you need to create instances from the four concrete handlers (receiver) classes that we created. Then you need to set the successor as in the below. The chain happens here. So you can change the chaining from the main program without changing the real implementation logic. Now you can create some bank accounts using the bank account constructor and give the amount that you want to withdraw.

The output of the program is given below.

Advantages of Chain of Responsibility Design Pattern

  1. To reduce the coupling degree. Decoupling it will request the sender and receiver.
  2. Simplified object. The object does not need to know the chain structure.
  3. Enhance flexibility by changing the members within the chain or change their order, allow dynamically adding or deleting responsibility.
  4. Increase the request processing new class of very convenient.

Disadvantages of Chain of Responsibility Design Pattern

  1. The request must be received not guarantee.
  2. The performance of the system will be affected, but also in the code debugging is not easy may cause cycle call.

When to use Chain of Responsibility Design Pattern

  1. When you want to decouple a request’s sender and receiver.
  2. Multiple objects, determined at runtime, are candidates to handle a request
  3. When you want to issue a request to one of several objects without specifying the receiver explicitly.

So this is the end of this article. I hope you learn about the chain of responsibility design pattern. I will put the GitHub repository link in the references. The next article will be the Memento design pattern. So stay in touch.

--

--