The chain of responsibility is similar to a linked list. Here the node is the class that has the knowledge of the next class and the value is the method handler. This is mainly used in vending machines like ATMs and logging frameworks.
ATM vending Machine Design
Logging Design
Designing Logging System
Logging Processor:
package Processor;
public abstract class LogProcessor {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
private LogProcessor nextLoggerProcessor;
public LogProcessor(LogProcessor nextLoggerProcessor){
this.nextLoggerProcessor = nextLoggerProcessor;
}
public void log(int logLevel, String message) {
if (nextLoggerProcessor != null) {
nextLoggerProcessor.log(logLevel, message);
}
}
}
Request Handlers:
package Processor;
public class InfoLogProcessor extends LogProcessor{
public InfoLogProcessor(LogProcessor nextLoggerProcessor) {
super(nextLoggerProcessor);
}
@Override
public void log(int logLevel, String message) {
if (logLevel == INFO){
System.out.println("INFO: "+ message);
} else {
super.log(logLevel, message);
}
}
}
package Processor;
public class ErrorLogProcessor extends LogProcessor{
public ErrorLogProcessor(LogProcessor nextLoggerProcessor) {
super(nextLoggerProcessor);
}
@Override
public void log(int logLevel, String message) {
if (logLevel == ERROR){
System.out.println("ERROR: "+ message);
} else {
super.log(logLevel, message);
}
}
}
package Processor;
public class DebugLogProcessor extends LogProcessor{
public DebugLogProcessor(LogProcessor nextLoggerProcessor) {
super(nextLoggerProcessor);
}
@Override
public void log(int logLevel, String message) {
if (logLevel == DEBUG){
System.out.println("DEBUG: "+ message);
} else {
super.log(logLevel, message);
}
}
}
Usage:
import Processor.DebugLogProcessor;
import Processor.ErrorLogProcessor;
import Processor.InfoLogProcessor;
import Processor.LogProcessor;
public class Main {
public static void main(String[] args) {
LogProcessor logProcessor = new InfoLogProcessor(new DebugLogProcessor(new ErrorLogProcessor(null)));
logProcessor.log(LogProcessor.ERROR, "Exceptions occurred");
logProcessor.log(LogProcessor.INFO, "Just for info");
logProcessor.log(LogProcessor.DEBUG, "Need to debug this");
}
}
Concise Description: In our logging system design, we've developed an abstract class that serves as a template for loggers. This abstract class contains the logger's fundamental structure, including a private variable that holds the reference to the next logger and a log
method for passing logs to the next logger. It's worth noting that at this stage, the loggers only perform log passing, with no additional functionality. Additionally, there are three static variables for storing mapped values related to info, error, and debug logs.
All other request handlers or loggers in the system extend this base class. To create a logger, you must provide the reference to the next logger in the constructor during initialization. If there are no subsequent loggers, you can pass null
as the reference.