Chain of responsibility - lambda function implementation [closed]
Asked Answered
M

1

-3

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.)

Muffler answered 7/4, 2016 at 18:33 Comment(4)
The problem is that you seem to have done no research or taken any effort to do this before posting your question here. You cannot ask people to write or share code for you. See the current Java implementation of the pattern, learn Lambda expression. Try to come up with your own implementation using Lamda's and then you can ask people so as to why your code is not working or if it can be improved. Good luck!Irrelevant
I spent at least 30 minutes googling for Chain of Responsibility lambda. And the best I came to was that grahamlea.com/2014/07/lambda-design-patterns-java-8Muffler
I realy dont understand. This is one of the GOF patterns. There is a lot of resource online about Command and Lamda, Strategy and lamda, Decorator and Lamda. And I have not seen anything about CoF and lamda. I still dont get what is wrong with that question. But ok good. Bad question.Muffler
You might look into Consumer.andThen() for clues on how it might be approachedMccammon
P
15

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;
        }
    }
}
Perpetuity answered 8/4, 2016 at 9:13 Comment(1)
Thats an awsome answer.Muffler

© 2022 - 2024 — McMap. All rights reserved.