How would you implement Chain of Responsibility pattern using Lambda in Java 8?
I only found a paragraph in this article:
Chain of responsibility
A lambda that may or may not delegate to another lambda, which may or may not delegate to another lambda, ad infinitum. (How to get the ‘next’ reference into the lambda is left as an exercise for the reader.)
I have adapted the java example from the wikipedia article:
In this example we have different roles, each having a fixed purchasing limit and a successor. Every time a user in a role receives a purchase request that exceeds his or her limit, the request is passed to his or her successor.
A builder allow to build a chain of handler :
public class Main {
public static void main(String[] args) {
final double base = 500;
ChainBuilder<PurchaseRequest> chainBuilder = ChainBuilder.chainBuilder();
Chain<PurchaseRequest> chain = chainBuilder
.first(request -> {
if (request.getAmount() < base * 10) {
System.out.println("Manager will approve $" + request.getAmount());
return true;
}
return false;
})
.successor(request -> {
if (request.getAmount() < base * 20) {
System.out.println("Director will approve $" + request.getAmount());
return true;
}
return false;
})
.successor(request -> {
if (request.getAmount() < base * 50) {
System.out.println("President will approve $" + request.getAmount());
} else {
System.out.println("Your request for $" + request.getAmount() + " needs a board meeting!");
}
return true;
}).build();
chain.handle(new PurchaseRequest(1000)); // manager
chain.handle(new PurchaseRequest(9000)); // director
chain.handle(new PurchaseRequest(23000)); // president
chain.handle(new PurchaseRequest(100000)); // board
}
private static class PurchaseRequest {
private final double amount;
private PurchaseRequest(double amount) {
this.amount = amount;
}
public double getAmount() {
return amount;
}
}
}
The lambda implements the functional interface Handler
. true
is return if the request was handled, false
if the request should be processed by the successor:
public interface Handler<T> {
boolean handle(T t);
}
The Chain
is a basic a consumer-like interface:
public interface Chain<T> {
void handle(T t);
}
the builder implementation:
public class ChainBuilder<T> {
public static <T> ChainBuilder<T> chainBuilder() {
return new ChainBuilder<>();
}
private HandlerImpl<T> first;
private ChainBuilder() {
}
public SuccessorBuilder first(Handler<T> handler) {
first = new HandlerImpl<>(handler);
return new SuccessorBuilder(first);
}
public class SuccessorBuilder {
private HandlerImpl<T> current;
private SuccessorBuilder(HandlerImpl<T> current) {
this.current = current;
}
public SuccessorBuilder successor(Handler<T> successor) {
HandlerImpl<T> successorWrapper = new HandlerImpl<>(successor);
current.setSuccessor(successorWrapper);
current = successorWrapper;
return this;
}
public Chain<T> build() {
return new ChainImpl<T>(first);
}
}
private static class ChainImpl<T> implements Chain<T> {
private final Handler<T> first;
public ChainImpl(Handler<T> first) {
this.first = first;
}
@Override
public void handle(T t) {
first.handle(t);
}
}
private static class HandlerImpl<T> implements Handler<T> {
private final Handler<T> delegate;
private Handler<T> successor;
public HandlerImpl(Handler<T> delegate) {
this.delegate = delegate;
}
private void setSuccessor(HandlerImpl<T> successor) {
this.successor = successor;
}
@Override
public boolean handle(T t) {
if (delegate.handle(t)) {
return true;
}
else if (successor != null) {
return successor.handle(t);
}
return false;
}
}
}