Implementation of the Chain of Responsibility Design Pattern in Java with multiple children / Real world complex workflow example
Hi,
You know Chain of Responsibility is featured in the Design Patterns book written by Gof(Gangs of Four). Nowadays I’m going over it again. I strongly recommend reading the book.
This pattern allows passing request/objects along the chain of potential handlers until one of them handles the request.
When I check the book’s examples and also I researched other examples from internet, I could not see any complex workflow implementation. All of the implementations I saw were straight and simple chains. Like below.
But, What if there are multiple chains with multiple arms. Like below.
You know some business flows are not simple enough to implement in a single chain often.
So I implemented the below workflow for you as an example.
There are handlers in the above workflow. They are checking customer VIP status, age, license date and order amount. Finally, an order is created or an exception is thrown. May be it does not make sense to you, I just made it up :)
OrderHandler -> abstact handler class
VipHandler -> check if the customer is VIP
AgeControlHandler -> checks if the customer is younger than 18
LicenseDateControlHandler -> checks the remaining license days
BalanceControlHandler -> checks if the balance is sufficient
CreateOrderHandler -> creates the order
Implementation
Handle method is the executer method. IsValid() checks if this order is a valid order or not for the current processor handler. If it is valid and if there is no “YES” result link (answerIsYesOrderHandler is null) then the current handler creates the order. If there are next handlers (YES or NO), the handler calls the next handler according to the isValid() return value.
abstract class OrderHandler {
private OrderHandler answerIsYesOrderHandler;
private OrderHandler answerIsNoOrderHandler;
private final String name;
private final String message;
protected OrderHandler(String name, String message) {
this.name = name;
this.message = message;
}
public void handle(Customer customer, Order order) throws Exception {
System.out.println("handler name : " + name);
if (isValid(customer, order)) {
if (answerIsYesOrderHandler != null) {
answerIsYesOrderHandler.handle(customer, order);
} else {
createOrder(order);
}
} else {
if (answerIsNoOrderHandler != null) {
answerIsNoOrderHandler.handle(customer, order);
} else {
throw new Exception(message);
}
}
}
private void createOrder(Order order){
System.out.println("Order is created successfully. Order : " + order);
}
protected abstract boolean isValid(Customer customer, Order order);
public void setAnswerIsYesOrderHandler(OrderHandler answerIsYesOrderHandler) {
this.answerIsYesOrderHandler = answerIsYesOrderHandler;
}
public void setAnswerIsNoOrderHandler(OrderHandler answerIsNoOrderHandler) {
this.answerIsNoOrderHandler = answerIsNoOrderHandler;
}
}
I implemented the create order method in the abstract handler class.
Order chain factory class;
public class OrderChainBuilder {
public static OrderHandler getOrderChain() {
OrderHandler createOrderHandler = new CreateOrderHandler("CreateOrderHandler", "Order create error");
OrderHandler balanceControlHandler = new BalanceControlHandler("BalanceControlHandler", "Not enough balance");
balanceControlHandler.setAnswerIsYesOrderHandler(createOrderHandler);
OrderHandler licenseDateControlHandler = new LicenseDateControlHandler("LicenseDateControlHandler", "License expired");
licenseDateControlHandler.setAnswerIsNoOrderHandler(balanceControlHandler);
licenseDateControlHandler.setAnswerIsYesOrderHandler(createOrderHandler);
OrderHandler ageControlHandler = new AgeControlHandler("AgeControlHandler", "Age is not valid");
ageControlHandler.setAnswerIsNoOrderHandler(licenseDateControlHandler);
ageControlHandler.setAnswerIsYesOrderHandler(balanceControlHandler);
OrderHandler vipHandler = new VipHandler("VipHandler", "Not a vip customer");
vipHandler.setAnswerIsNoOrderHandler(ageControlHandler);
vipHandler.setAnswerIsYesOrderHandler(createOrderHandler);
return vipHandler;
}
private OrderChainBuilder() {
}
}
Source code is below;
In my repo, there are lots of pattern implementations and explanations in the readme files. While coding the all examples, I especially paid attention to make it logical and plausible. Please feel free to contact me to fix the issues. I would love to hear your comments.
Thank you for reading :)