-1

I'm trying to implement an action/reaction system in Java.
For that, I need to have all my methods stock in a container so I can easily call the response I need with the return of the action I want.
Being a C ++ developer and new to Java my first intuition was to create an array of function pointers (or at least reproduce it) so I tried to used anonymous subclasses. But didn't get the result I was looking for.
So I tried with lambdas, here is a sample of what I'm trying to do.

    public class Test {
      public Map<Integer, Vector<String>> actions = new HashMap<>();
      public Map<Integer, Integer> responses = new HashMap<>();

      public Test() {
        Vector<String> v= new Vector<String>();

        actions.put(0, action0());
        actions.put(1, action1());
        responses.put(0, response0(Vector<String>)); // How can I leave aside this argument which I don't know at this point ?
        responses.put(1, response1(Vector<String>));
      }

      public Vector<String> action0() {...}
      public Vector<String> action1() {...}

      // This methods takes actions return as argument
      public Integer response0 (Vector<String>) {...}
      public Integer response1 (Vector<String>) {...}

      public void run() {
        // When I run, I want to be able to launch any of my responses with any of my actions return
        responses.get(0) 
      }
   }

Am I at least trying a good way to solve this problem ?
Thanks a lot

  • I can't understand your question well. Do you want to do call "action" and with that return value call "response"? – SungJin Steve Yoo Oct 29 '17 at 02:30
  • I don't want to stray off topic but, unless this approach is mandatory, you might want to look at `RxJava`. – ChiefTwoPencils Oct 29 '17 at 02:30
  • ...and since you're coming from C++ to Java, are you sure a [`Vector`](https://stackoverflow.com/questions/1386275/why-is-java-vector-class-considered-obsolete-or-deprecated) is what you want to use? – ChiefTwoPencils Oct 29 '17 at 02:33
  • @SungJinSteveYoo Yes that's exactly what I want to do But I have tons of actions and responses that's why I'm trying to find an elegant and parameterized way to bind response to action – Gobind Willy Oct 29 '17 at 02:34
  • 3
    as ChiefTwoPencils said, Java's `Vector` is different from C++'s `vector`. equivalent data structure is `ArrayList`. And also he is right, using `RxJava` will give you the implementation that you want – SungJin Steve Yoo Oct 29 '17 at 02:35
  • 1
    I will say look at command pattern that even java swing adapts... i.e how you register an action listener to a component, and then when action is performed, you invoke your response code – Optional Oct 29 '17 at 02:39
  • Well Thanks, gonna change from Vector to ArrayList, but my real issue is to find a way to stock all of my methods without creating multiple conditions to match actions and reponses – Gobind Willy Oct 29 '17 at 02:40
  • plz update your `run()` method's code to clarify the behaviour that you want – SungJin Steve Yoo Oct 29 '17 at 02:45
  • Yes, please update your code. You have inconsistencies that apparently require a few assumptions. – ChiefTwoPencils Oct 29 '17 at 02:49

1 Answers1

-2

Your code has a few flaws, so I'll assume that getHashtag() and action1() were supposed to be the same, and similar for the other three.

Also, I'll assume that the second responses.put() should have been key 1, not 0. Also, the parameter to your responseX() methods need a name.

Anyway, you need a functional interface, so you can give the responseX() methods as Method References.

In your case, the responseX() methods take a Vector<String> as parameter, and returns an Integer, so the functional interface would be Function<Vector<String>, Integer>.

You can then build a map of those methods, to be executed later.

public Test() {
    // Here we can build map of response methods first, if we like, even though Vectors don't exist yet
    Map<Integer, Function<Vector<String>, Integer>> responseMethods = new HashMap<>();
    responseMethods.put(0, this::response0);
    responseMethods.put(1, this::response1);

    // Now we build the action map of Vectors
    Map<Integer, Vector<String>> actions = new HashMap<>();
    actions.put(0, action0());
    actions.put(1, action1());

    // At this time, we can now execute the referenced methods to get the actual responses
    Map<Integer, Integer> responses = new HashMap<>();
    for (Integer key : actions.keySet()) {
        Vector<String> v = actions.get(key);
        Function<Vector<String>, Integer> responseMethod = responseMethods.get(key);
        Integer response = responseMethod.apply(v);
        responses.put(key, response);
    }
}

public Vector<String> action0() {...}
public Vector<String> action1() {...}

public Integer response0(Vector<String> v) {...}
public Integer response1(Vector<String> v) {...}

You can even defer the execution of the action methods if you want:

public Test() {
    // Here we can build map of response methods first, if we like, even though Vectors don't exist yet
    Map<Integer, Function<Vector<String>, Integer>> responseMethods = new HashMap<>();
    responseMethods.put(0, this::response0);
    responseMethods.put(1, this::response1);

    // Now we build the action map of Vectors
    Map<Integer, Supplier<Vector<String>>> actionMethods = new HashMap<>();
    actionMethods.put(0, this::action0);
    actionMethods.put(1, this::action1);

    // At this time, we can now execute the referenced methods to get the actual responses
    Map<Integer, Integer> responses = new HashMap<>();
    for (Integer key : actionMethods.keySet()) {
        Supplier<Vector<String>> actionMethod = actionMethods.get(key);
        Function<Vector<String>, Integer> responseMethod = responseMethods.get(key);
        Vector<String> v = actionMethod.get();
        Integer response = responseMethod.apply(v);
        responses.put(key, response);
    }
}
Andreas
  • 154,647
  • 11
  • 152
  • 247