Αγαπητοί,
μπορείτε να με βοηθήσετε σε ένα API design;
Ίσως θυμάστε από το Swing ή το GWT τα event handlers. Η ιδέα είναι πως απεμπλέκεις δυο κομμάτια Α και Β που έχουν λειτουργική αναφορά το ένα στο άλλο. Δηλ πες πως στην έχεις κάτι του στυλ:
class A{
void logUserEnteredWrongPassword(String user){
logger.warn("user "+user+" entered wrong password");
}
}
class B{
A a;
void login(String user, String password){
if (!...) a.logUserEnteredWrongPassword(user);
}
}
Εδώ το Β έχει μια εξάρτηση από το Α. Με events αυτό γράφεται:
class A implements UserAuthenticationEventListener{
public A(EventBus bus){
bus.addListener(this);
}
@Override
void onUserEnteredWrongPassword(UserAuthenticationEvent e){
logger.warn("user "+e.user+" entered wrong password");
}
}
class B{
EventBus bus;
void login(String user, String password){
if (!...) bus.fireEvent(new UserAuthenticationEvent(fail, user))M
}
}
Για κάθε λειτουργία πρέπει να:
- φτιάξεις μια event κλάση
- φτιάξεις ένα listener
- θες ένα event bus
- να τα δέσεις
Επειδή (εδώ) υπάρχει 1:1 αντιστοιχεία μεταξύ events και listeners βρήκα τρόπο
με java 8 lambdas να απλοποιήσω το event bus και να δουλεύει χωρίς
events, πετυχαίνοντας όμως την ανεξαρτητοποίηση του Α από το Β.
Ο κώδικας του event bus είναι εδώ: https://github.com/ggeorgovassilis/superstartrek/tree/gh-pages/src/main/java/superstartrek/client/bus
Τα unit tests είναι εδώ:
https://github.com/ggeorgovassilis/superstartrek/tree/gh-pages/src/test/java/genericsbus
Παρά την σημαντική απλοποίηση παραμένει το κάπως πολύπλοκο συντακτικό όταν στέλνεις events:
bus.invoke(Events.EVENT2, (Callback<Handler2>) ((h) -> h.method2("p1","p2")));
Το casting στο lambda callback χρειάζεται για να ξέρει ο compiler τι είδους interface είναι το h. Βλέπετε κάτι απλούστερο;
interface SomeHandler{
void method1(int a, int b);
}
...
Event<SomeHandler> SOME_EVENT = new Event<>();
...
bus.invoke(SOME_EVENT, (h)->h.method1(77,88));