×

iFour Logo

A complete guide on Behavioral Design Pattern and Chain of Responsibility Pattern in Java

Kapil Panchal - September 13, 2021

Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

  • play
  • pause
  • pause
A complete guide on Behavioral Design Pattern and Chain of Responsibility Pattern in Java

Table of Content

In this blog, we’ll learn behavioral design patterns where and when we can use this particular pattern, and its types.

Also, we’ll particularly focus on the chain of responsibility pattern which is a type of behavioral design pattern.

What is Behavioral Design Pattern?


A design pattern in which more emphasis is given to how the objects interact with each other.

Also as the name suggests a chain of responsibility i.e., objects have their responsibilities/tasks to perform.

In behavioral design patterns, there should be minimum hard coding, the objects should be loosely coupled and coherence should be more.

Now, let us understand the terms coupling and coherence. These are significant terms in design patterns and also in software engineering.

Coupling - Coupling means interdependency here in terms of objects. The objects should be less dependent on each other for a particular task, otherwise, due to a failure or delay in one object can lead to a system failure.

Coherence - Coherence means that the objects/modules should work together so that they complement each other rather than creating a burden on the system.

Types of Behavioral Design Pattern:


  1. Interpreter Pattern: As the name suggests it is used to interpret a pattern in a particular way.

  2. Mediator Pattern: This design pattern acts as a mediator between different classes so that they can communicate properly and loosely coupled manner.

  3. Command Pattern: Here the request by the client is wrapped and converted into a command. It is also known as a data-driven pattern.

  4. State Pattern: As the name suggests, it is related to the state of an object in different classes.

  5. Chain of Responsibility Pattern: Used when we want a chain of objects.

  6. Memento Pattern: This design pattern is used when we want to change the state of an object to the previous form.

  7. Template Pattern: In template pattern, there is an abstract class which set the implementation so other class can use them according to it.

  8. Visitor Pattern: In this method, there is a visitor class that will change the algorithm of the particular element.

  9. Null Object: We use this pattern when we have null values and do nothing relationship.

  10. Strategy Pattern: We can use this pattern when we want to change the algorithm or behavior of a class at runtime.

  11. Iterator Pattern: This is one of the most common design patterns, it is used when want to access data sequentially from a collection. In java, iterator pattern is used in iterator also.

  12. Observer Pattern: When we want to observe and respond according to change in an object we use an observer pattern. When an object changes its relationship with other objects which are in entity-relationship also changes so, we need observer pattern.

What is a Chain of Responsibility Pattern?


A design pattern in which objects show a chain behavior is a chain of responsibility pattern.

Whenever a user sends a request it passes through a chain of an object and any object can send a response accordingly. So there is the least coupling between the objects.

Advantages of using Chain of Responsibility Pattern:


  • Less coupling in the system, so less interdependency.

  • The structure becomes more flexible due to less coupling and more coherence.

Example for Chain of Responsibility Pattern:


Now, let us understand the chain of responsibility pattern with an example. The given below UML diagram will make you easily understand.

UML_Diagram

 

[Source]

 

So here we have three different logger class which extends the main abstract logger class and a client class.

Each class has its attributes and methods like Logger has output info, error info, debug info as attributes, and set Logger, Message, display Log Info as methods.

Console Based Logger class has a console-based logger and displays Log Info as methods but no attributes of its own. Debug Based Logger has Debug Based Logger(int levels) and displays Log Info as methods but no attributes of it

The client class which is Chain of Responsibility Client has de chain() and main methods.

Main logger class

public abstract class Logger {  
    public static int OUTPUTINFO = 1;  
    public static int ERRORINFO = 2;  
    public static int DEBUGINFO = 3;  
    protected int levels;  
    protected Logger nextLevelLogger;  
public void setNextLevelLogger( Logger nextLevelLogger ) 
{  
        this.nextLevelLogger = nextLevelLogger;  
    }  
        public void logMessage( int levels, String msg )
{  
        if(this.levels <= levels){  
            displayLogInfo(msg);  
        }  
        if (nextLevelLogger != null) {  
            nextLevelLogger.logMessage(levels, msg);  
        }  
    }  
    protected abstract void displayLogInfo(String msg);  
}  

Console based logger class

public class DebugBasedLogger extends Logger {  
  public DebugBasedLogger(int levels) {  
      this.levels = levels;  
  }  
  @Override  
  protected void displayLogInfo(String msg) {  
      System.out.println("DEBUG LOGGER INFO: " + msg);  
  }  
}

Error based logger class

public class ErrorBasedLogger extends Logger {  
  public ErrorBasedLogger(int levels) {  
      this.levels=levels;  
  }  
  @Override  
  protected void displayLogInfo(String msg) {  
      System.out.println("ERROR LOGGER INFO: " + msg);  
  }  
}

Client class / main class

public class ChainofResponsibilityClient {  
  private static Logger doChaining(){  
    Logger consoleLogger = new ConsoleBasedLogger(Logger.OUTPUTINFO);  

    Logger errorLogger = new ErrorBasedLogger(Logger.ERRORINFO);  
    consoleLogger.setNextLevelLogger(errorLogger);  
            
    Logger debugLogger = new DebugBasedLogger(Logger.DEBUGINFO);  
    errorLogger.setNextLevelLogger(debugLogger);  
            
    return consoleLogger;   
    }  
    public static void main(String args[]){  
    Logger chainLogger = doChaining();  
  
        chainLogger.logMessage(Logger.OUTPUTINFO, "Enter the sequence of values ");  
        chainLogger.logMessage(Logger.ERRORINFO, "An error has occurred now");  
        chainLogger.logMessage(Logger.DEBUGINFO, "This was the error now debugging is compiled");  
        }  
}  

Output:

AbilityClient

CONSOLE LOGGER INFO: Enter the sequence of values

CONSOLE LOGGER INFO: An error has occurred now

ERROR LOGGER INFO: An error has occurred now

CONSOLE LOGGER INFO: This was the error now debugging is compiled

ERROR LOGGER INFO: This was the error now debugging is compiled

DEBUG LOGGER INFO: This was the error now debugging is compiled

Conclusion


So in this blog, we focused learning on the chain of responsibility pattern which is one of the behavioral design patterns, its uses, advantages, and also when to use these design patterns, etc. along with an example.

A complete guide on Behavioral Design Pattern and Chain of Responsibility Pattern in Java Table of Content 1. What is Behavioral Design Pattern? 2. Types of Behavioral Design Pattern: 3. What is a Chain of Responsibility Pattern? 4. Advantages of using Chain of Responsibility Pattern: 5. Example for Chain of Responsibility Pattern: 6. Conclusion In this blog, we’ll learn behavioral design patterns where and when we can use this particular pattern, and its types. Also, we’ll particularly focus on the chain of responsibility pattern which is a type of behavioral design pattern. What is Behavioral Design Pattern? A design pattern in which more emphasis is given to how the objects interact with each other. Also as the name suggests a chain of responsibility i.e., objects have their responsibilities/tasks to perform. In behavioral design patterns, there should be minimum hard coding, the objects should be loosely coupled and coherence should be more. Now, let us understand the terms coupling and coherence. These are significant terms in design patterns and also in software engineering. Coupling - Coupling means interdependency here in terms of objects. The objects should be less dependent on each other for a particular task, otherwise, due to a failure or delay in one object can lead to a system failure. Coherence - Coherence means that the objects/modules should work together so that they complement each other rather than creating a burden on the system. Read More: A Complete Guide On Structural Design Pattern In Java Types of Behavioral Design Pattern: Interpreter Pattern: As the name suggests it is used to interpret a pattern in a particular way. Mediator Pattern: This design pattern acts as a mediator between different classes so that they can communicate properly and loosely coupled manner. Command Pattern: Here the request by the client is wrapped and converted into a command. It is also known as a data-driven pattern. State Pattern: As the name suggests, it is related to the state of an object in different classes. Chain of Responsibility Pattern: Used when we want a chain of objects. Memento Pattern: This design pattern is used when we want to change the state of an object to the previous form. Template Pattern: In template pattern, there is an abstract class which set the implementation so other class can use them according to it. Visitor Pattern: In this method, there is a visitor class that will change the algorithm of the particular element. Null Object: We use this pattern when we have null values and do nothing relationship. Strategy Pattern: We can use this pattern when we want to change the algorithm or behavior of a class at runtime. Iterator Pattern: This is one of the most common design patterns, it is used when want to access data sequentially from a collection. In java, iterator pattern is used in iterator also. Observer Pattern: When we want to observe and respond according to change in an object we use an observer pattern. When an object changes its relationship with other objects which are in entity-relationship also changes so, we need observer pattern. What is a Chain of Responsibility Pattern? A design pattern in which objects show a chain behavior is a chain of responsibility pattern. Whenever a user sends a request it passes through a chain of an object and any object can send a response accordingly. So there is the least coupling between the objects. Advantages of using Chain of Responsibility Pattern: Less coupling in the system, so less interdependency. The structure becomes more flexible due to less coupling and more coherence. Searching for Reliable Java Development Company ? CONTACT US Example for Chain of Responsibility Pattern: Now, let us understand the chain of responsibility pattern with an example. The given below UML diagram will make you easily understand.   [Source]   So here we have three different logger class which extends the main abstract logger class and a client class. Each class has its attributes and methods like Logger has output info, error info, debug info as attributes, and set Logger, Message, display Log Info as methods. Console Based Logger class has a console-based logger and displays Log Info as methods but no attributes of its own. Debug Based Logger has Debug Based Logger(int levels) and displays Log Info as methods but no attributes of it The client class which is Chain of Responsibility Client has de chain() and main methods. Main logger class public abstract class Logger { public static int OUTPUTINFO = 1; public static int ERRORINFO = 2; public static int DEBUGINFO = 3; protected int levels; protected Logger nextLevelLogger; public void setNextLevelLogger( Logger nextLevelLogger ) { this.nextLevelLogger = nextLevelLogger; } public void logMessage( int levels, String msg ) { if(this.levels <= levels){ displayLogInfo(msg); } if (nextLevelLogger != null) { nextLevelLogger.logMessage(levels, msg); } } protected abstract void displayLogInfo(String msg); } Console based logger class public class DebugBasedLogger extends Logger { public DebugBasedLogger(int levels) { this.levels = levels; } @Override protected void displayLogInfo(String msg) { System.out.println("DEBUG LOGGER INFO: " + msg); } } Error based logger class public class ErrorBasedLogger extends Logger { public ErrorBasedLogger(int levels) { this.levels=levels; } @Override protected void displayLogInfo(String msg) { System.out.println("ERROR LOGGER INFO: " + msg); } } Client class / main class public class ChainofResponsibilityClient { private static Logger doChaining(){ Logger consoleLogger = new ConsoleBasedLogger(Logger.OUTPUTINFO); Logger errorLogger = new ErrorBasedLogger(Logger.ERRORINFO); consoleLogger.setNextLevelLogger(errorLogger); Logger debugLogger = new DebugBasedLogger(Logger.DEBUGINFO); errorLogger.setNextLevelLogger(debugLogger); return consoleLogger; } public static void main(String args[]){ Logger chainLogger = doChaining(); chainLogger.logMessage(Logger.OUTPUTINFO, "Enter the sequence of values "); chainLogger.logMessage(Logger.ERRORINFO, "An error has occurred now"); chainLogger.logMessage(Logger.DEBUGINFO, "This was the error now debugging is compiled"); } } Output: AbilityClient CONSOLE LOGGER INFO: Enter the sequence of values CONSOLE LOGGER INFO: An error has occurred now ERROR LOGGER INFO: An error has occurred now CONSOLE LOGGER INFO: This was the error now debugging is compiled ERROR LOGGER INFO: This was the error now debugging is compiled DEBUG LOGGER INFO: This was the error now debugging is compiled Conclusion So in this blog, we focused learning on the chain of responsibility pattern which is one of the behavioral design patterns, its uses, advantages, and also when to use these design patterns, etc. along with an example.
Kapil Panchal

Kapil Panchal

A passionate Technical writer and an SEO freak working as a Content Development Manager at iFour Technolab, USA. With extensive experience in IT, Services, and Product sectors, I relish writing about technology and love sharing exceptional insights on various platforms. I believe in constant learning and am passionate about being better every day.

Build Your Agile Team

Enter your e-mail address Please enter valid e-mail

Categories

Ensure your sustainable growth with our team

Talk to our experts
Sustainable
Sustainable
 
Blog Our insights
13 Ways Power Apps Simplifies eDiscovery
13 Ways Power Apps Simplifies eDiscovery

E-Discovery is a crucial process for legal research enabling lawyers to find the digital evidence they need. It involves finding, collecting, and filtering e-data related to their...

Top Data Analytics Trends You Can't Ignore
Top Data Analytics Trends You Can't Ignore

Can you believe that 147 zettabytes of data have already been created in 2024, and guess what? It is anticipated to be 180 zettabytes by 2025 (according to Statista). Now just think...

Why Use Power Apps for Case Management – 11 Reasons
Why Use Power Apps for Case Management – 11 Reasons

It’s amazing to witness that legal consultants who once clung to print documents have now embraced modern technologies for their legal work. In fact, a recent survey revealed that over 72% of law firms employ cloud-based technologies for managing case files, scheduling, and billing. This shift is not just about convenience; it’s about the progress we observe in the legal field.