DEV Community

Cover image for A complete guide on Behavioral Design Pattern and Chain of Responsibility Pattern in Java
Harshal Suthar
Harshal Suthar

Posted on • Originally published at ifourtechnolab.com

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

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?

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.

Image description
[Img 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);  
}  

Enter fullscreen mode Exit fullscreen mode

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);  
  }  
}

Enter fullscreen mode Exit fullscreen mode

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);  
  }  
}

Enter fullscreen mode Exit fullscreen mode

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");  
        }  
}  

Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)