Chain of Responsibility Pattern

Chain of responsibility design pattern creates a chain of request handlers to process a client's request. Each request handler in chain contains reference of next request handler in the chain. If one request handler cannot handle the request then it passes the request to the next handler in the chain. The request handlers in the chain will decide themselves on runtime that who will process the request and whether request needs to be forwarded to next handler in chain or not.

The request object is sent to a chain of request handler objects. The request can be processed by any request handler in the chain. This pattern comes under behavioral patterns.

Usage of Chain of Responsibility Pattern

  • When we want to decouple a request and request handlers.

  • When we want a single request processing pipeline that contains multiple possible request handlers arranges in some specific sequence.

  • When we don’t want to specify request handlers explicitly in your code, instead want to select appropriate handler on runtime based on request data.

Important Points about Chain of Responsibility Pattern

  • Client doesn’t know which request handler will process the request and it will just send the request to the first handler in the chain.

  • Each request handler in the chain will have it’s own specific implementation to handle the request or to send it to the next object in the chain. Each request handler(except the last handler in chain) must have reference to the next handler in chain.

  • The hadlers in the chain should be arranged properly such that a request will reach it's corresponding handler. It is recommended to create a default request handler at the end of chain to process a request If none of the handler can process a request.

Implementation of Chain of Responsibility Pattern

Chain of Responsibility Design Pattern UML diagram First of all, we will create an enum class called NotificationType for different type of notifications including SMS, EMAIL and MAIL. NotificationType.java
public enum NotificationType {
    SMS,
    EMAIL,
    MAIL
}

AbstractHandler.java
AbstractHandler is an abstract class which contains reference of next handler in chain and declares sendNotification method which sends notification or forward request to next handler in chain. It declares an abstract method sendMessage which is implemented by all notification handlers. Notification handler classes of all three notification types(SMS, EMAIL and MAIL) will have specific implemention for sending different types of notification.
public abstract class AbstractHandler {
    protected NotificationType messageType;

    protected AbstractHandler nextHandler;

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

    public void sendNotification(NotificationType messageType, String message){
        if(this.messageType == messageType){
            sendMessage(message);
            return;
        }
        if(nextHandler !=null){
            System.out.println("Sending message to next handler");
            nextHandler.sendNotification(messageType, message);
        }
    }
    abstract void sendMessage(String message);
}

SmsNotificationHandler.java
public class SmsNotificationHandler extends AbstractHandler {

    public SmsNotificationHandler(NotificationType messageType) {
        this.messageType = messageType;
    }

    @Override
    protected void sendMessage(String message) {
        System.out.println("Sending message via SMS: " + message);
    }
}

EmailNotificationHandler.java
public class EmailNotificationHandler extends AbstractHandler {

    public EmailNotificationHandler(NotificationType messageType) {
        this.messageType = messageType;
    }

    @Override
    protected void sendMessage(String message) {
        System.out.println("Sending message via Email: " + message);
    }
}

MailNotificationHandler.java
public class MailNotificationHandler extends AbstractHandler {

    public MailNotificationHandler(NotificationType messageType) {
        this.messageType = messageType;
    }

    @Override
    protected void sendMessage(String message) {
        System.out.println("Sending message via Mail: " + message);
    }
}


NotificationHandlerChain.java
NotificationHandlerChain creates an instance of notification handler classes for each notification type and creates a handler chain by setting nextHandler field of each handler. SmsNotificationHandler is the first handler in chain followed by EmailNotificationHandler and then followed by MailNotificationHandler. The sendNotification method will send message to the handlerchain.
public class NotificationHandlerChain {
    private AbstractHandler smsHandler;
    private AbstractHandler emailHandler;
    private AbstractHandler mailHandler;

    private AbstractHandler handlerChain;

    public NotificationHandlerChain() {
        smsHandler = new SmsNotificationHandler(NotificationType.SMS);
        emailHandler = new EmailNotificationHandler(NotificationType.EMAIL);
        mailHandler = new MailNotificationHandler(NotificationType.MAIL);
        // Create handler chain SMS -> EMAIL -> MAIL
        smsHandler.setNextHandler(emailHandler);
        emailHandler.setNextHandler(mailHandler);
        // Set handler chain
        handlerChain = smsHandler;
    }
     public void sendNotification(NotificationType messageType, String message) {
         handlerChain.sendNotification(messageType, message);
     }
}

Client.java
Client class will first create an instance of NotificationHandlerChain and then send one notification for SMS, EMAIL and MAIL each. Based on the value of NotificationType, corresponding notification handler will send notification else message will be forwarded to next handler in chain.
public class Client {
    public static void main(String[] args) {
        NotificationHandlerChain handlerChain = new NotificationHandlerChain();
        // Send SMS Notification
        handlerChain.sendNotification(NotificationType.SMS, "Hello");
        // Send Email Notification
        handlerChain.sendNotification(NotificationType.EMAIL, "Hello");
        // Send Mail Notification
        handlerChain.sendNotification(NotificationType.MAIL, "Hello");
    }
}

Output

Sending message via SMS: Hello
Sending message to next handler
Sending message via Email: Hello
Sending message to next handler
Sending message to next handler
Sending message via Mail: Hello

Related Topics
Bridge Design Pattern
Template Design Pattern
Interpreter Design Pattern
Singleton Design Pattern
Builder Design Pattern
Memento Design Pattern
Observer Design Pattern
Factory Design Pattern
Prototype Design Pattern
State Design Pattern
List of Design Patterns