Overview
Pattern Type: Behavioral
Purpose: Allows passing requests along a chain of potential handlers until one of them handles the request. This pattern provides a way to process varying requests in a decentralized manner.
Key Components
Handler (Interface or Abstract Class): Provides a blueprint for handling requests and optionally implementing the successor link. Each handler decides whether to handle the request or pass it along the chain.
Concrete Handlers: Implement the handler interface and handle the requests they are responsible for. If they can't handle a request, they pass it on to the next handler in the chain.
Client: Initiates the request to the first handler in the chain.
Real-World Example
Context: A customer support system where a request (like a refund request) can be handled by multiple levels of personnel (e.g., a support agent, a supervisor, and a manager), depending on the complexity or amount of the refund.
Code Example (in Java)
// Handler
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(Request request);
}
// Concrete Handlers
public class SupportAgent extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.SIMPLE) {
System.out.println("Support Agent: Handling simple request.");
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
public class Supervisor extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.COMPLEX) {
System.out.println("Supervisor: Handling complex request.");
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
public class Manager extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.CRITICAL) {
System.out.println("Manager: Handling critical request.");
} else {
System.out.println("Manager: Escalated request to higher authority.");
}
}
}
// Request Type
public enum RequestType {
SIMPLE, COMPLEX, CRITICAL
}
// Request
public class Request {
private RequestType type;
public Request(RequestType type) {
this.type = type;
}
public RequestType getType() {
return type;
}
}
// Client code
public class Client {
public static void main(String[] args) {
Handler agent = new SupportAgent();
Handler supervisor = new Supervisor();
Handler manager = new Manager();
agent.setSuccessor(supervisor);
supervisor.setSuccessor(manager);
Request simpleRequest = new Request(RequestType.SIMPLE);
agent.handleRequest(simpleRequest);
Request complexRequest = new Request(RequestType.COMPLEX);
agent.handleRequest(complexRequest);
Request criticalRequest = new Request(RequestType.CRITICAL);
agent.handleRequest(criticalRequest);
}
}
Expanded Explanation
Handler (
Handler): Abstract class or interface defining how requests should be handled, and maintaining a reference to the next handler.Concrete Handlers (
SupportAgent,Supervisor,Manager): Specific handlers in the request processing chain. Each one handles requests of a specific type and delegates others to the next handler.Client (
Client): Initiates the requests and sets up the chain of handlers.
Benefits
Decoupled Components: Decouples the sender of the request from the receivers by giving more than one object a chance to handle the request.
Dynamic Handling: Allows dynamically adding or changing handlers within the chain.
Flexibility in Handling: Offers more flexibility in distributing responsibilities among objects.
Drawbacks
Processing Time: Handling a request may take longer as it might pass through multiple handlers.
Chain Configuration: Misconfiguration of the chain can lead to a request not being handled at all.
Applicability
Sequential Processing: Useful when several different objects are expected to process a request in sequence.
Conditional Handling: Effective in scenarios where a request can be handled by one of several potential handlers, based on runtime conditions.
Use Cases in Software Development
Event Handling in UI Frameworks: Used in graphical user interfaces where an event might be handled by multiple elements in the hierarchy.
Approval Processes: Common in workflows where different levels of authorization are required to approve or reject requests.
The Chain of Responsibility Pattern offers a robust framework for processing varied requests within a system