WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Design Patterns · Intermediate · question 32 of 100

Explain how the Chain of Responsibility pattern can be used to implement a centralized error handling mechanism.?

📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

The Chain of Responsibility pattern allows multiple objects to handle a request without knowing which object will handle it. This pattern can be used to implement a centralized error handling mechanism.

In this context, the Chain of Responsibility pattern would work as follows: each layer of the system (such as the data access layer, the business logic layer, or the presentation layer) would have its own error handler. These error handlers would be arranged in a chain of responsibility, where each error handler would be responsible for handling a specific type of error.

When an error occurs in the system, it would be caught by the first error handler in the chain. If that error handler cannot handle the error, it would pass the error on to the next error handler in the chain, and so on, until the error is either handled or there are no more error handlers to pass it to.

This approach has several advantages. First, it keeps error handling code organized and modular, allowing different parts of the system to have their own specific error handling logic. Second, it provides a centralized error handling mechanism, ensuring that all errors in the system are handled consistently. Third, it allows new error handlers to be easily added to the system as new types of errors are encountered or as existing error handling code is refactored.

Here is an example Java implementation of the Chain of Responsibility pattern for error handling:

public abstract class ErrorHandler {
    private ErrorHandler nextHandler;

    public void setNextHandler(ErrorHandler handler) {
        this.nextHandler = handler;
    }

    public void handleError(Error error) {
        if (canHandle(error)) {
            handle(error);
        } else if (nextHandler != null) {
            nextHandler.handleError(error);
        } else {
            // no error handler was able to handle this error
            throw new RuntimeException("Unhandled error: " + error.getMessage());
        }
    }

    protected abstract boolean canHandle(Error error);

    protected abstract void handle(Error error);
}

public class DataAccessErrorHandler extends ErrorHandler {
    @Override
    protected boolean canHandle(Error error) {
        // check if this error is a data access error
        return error instanceof DataAccessError;
    }

    @Override
    protected void handle(Error error) {
        // handle the data access error
        // ...
    }
}

public class BusinessLogicErrorHandler extends ErrorHandler {
    @Override
    protected boolean canHandle(Error error) {
        // check if this error is a business logic error
        return error instanceof BusinessLogicError;
    }

    @Override
    protected void handle(Error error) {
        // handle the business logic error
        // ...
    }
}

public class PresentationErrorHandler extends ErrorHandler {
    @Override
    protected boolean canHandle(Error error) {
        // check if this error is a presentation error
        return error instanceof PresentationError;
    }

    @Override
    protected void handle(Error error) {
        // handle the presentation error
        // ...
    }
}

In this example, the ‘ErrorHandler‘ class is the abstract base class for all error handlers. Each concrete error handler (such as ‘DataAccessErrorHandler‘, ‘BusinessLogicErrorHandler‘, and ‘PresentationErrorHandler‘) extends ‘ErrorHandler‘ and overrides the ‘canHandle‘ and ‘handle‘ methods.

The ‘canHandle‘ method checks if the error that was passed to the error handler can be handled by that error handler. If it can, the ‘handle‘ method is called to actually handle the error. If not, the error is passed on to the next error handler in the chain by calling ‘nextHandler.handleError(error)‘.

To use this error handling mechanism in our system, we would create an instance of each of the concrete error handlers and link them together in a chain of responsibility:

public class ErrorHandlerChain {
    private ErrorHandler firstHandler;

    public ErrorHandlerChain() {
        DataAccessErrorHandler dataAccessHandler = new DataAccessErrorHandler();
        BusinessLogicErrorHandler businessLogicHandler = new BusinessLogicErrorHandler();
        PresentationErrorHandler presentationHandler = new PresentationErrorHandler();

        dataAccessHandler.setNextHandler(businessLogicHandler);
        businessLogicHandler.setNextHandler(presentationHandler);

        firstHandler = dataAccessHandler;
    }

    public void handleError(Error error) {
        firstHandler.handleError(error);
    }
}

In this example, the ‘ErrorHandlerChain‘ class creates the instance of each concrete error handler and sets their next handlers. The ‘handleError‘ method in the ‘ErrorHandlerChain‘ class is the entry point for error handling in the system. When an error occurs, we would call ‘handleError‘ with the error object. The error would then be passed down the chain of responsibility until it is handled or until there are no more error handlers to pass it to.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Design Patterns interview — then scores it.
📞 Practice Design Patterns — free 15 min
📕 Buy this interview preparation book: 100 Design Patterns questions & answers — PDF + EPUB for $5

All 100 Design Patterns questions · All topics