For my Java game server I send the Action ID of the packet which basically tells the server what the packet is for. I want to map each Action ID (an integer) to a function.
Another similar aproach could be using Java 8's Suppliers:
Map<Integer, Supplier<T> suppliers = new HashMap();
suppliers.put(1, () -> methodOne());
suppliers.put(2, () -> methodTwo());
// ...
public T methodOne() { ... }
public T methodTwo() { ... }
// ...
T obj = suppliers.get(id).run();
You could interface static methods. This method allows you to specify parameters too. Declare your interface...
public interface RouteHandler {
void handleRequest(HttpExchange t) throws IOException;
}
And your map...
private Map<String, RouteHandler> routes = new HashMap<>();
Then implement static methods that match the interface/params...
public static void notFound(HttpExchange t) throws IOException {
String response = "Not Found";
t.sendResponseHeaders(404, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
You can then add those methods into your map...
routes.put("/foo", CoreRoutes::notFound);
and call them as follows...
RouteHandler handler = routes.get("/foo");
handler.handleRequest(exchange);
Java does not have first-class function pointers. In order to achieve similar functionality, you have to define and implement an interface. You can make it easier using anonymous inner classes, but it's still not very pretty. Here's an example:
public interface PacketProcessor
{
public void processPacket(Packet packet);
}
...
PacketProcessor doThing1 = new PacketProcessor()
{
public void processPacket(Packet packet)
{
// do thing 1
}
};
// etc.
// Now doThing1, doThing2 can be used like function pointers for a function taking a
// Packet and returning void
Have you ever used Swing/AWT? Their Event hierarchy solves a similar problem. The way Java passes functions around is with an interface, for example
public interface ActionHandler {
public void actionPerformed(ActionArgs e);
}
Then, if you want to map integers onto these objects, you could use something like a java.util.HashMap<Integer,ActionHandler>
to manage that. The actual implementations can either go in anonymous classes (Java's best approximation of "lambda") or in proper classes somewhere. Here's the anonymous class way:
HashMap<Integer,ActionHandler> handlers;
handlers.put(ACTION_FROB, new ActionHandler() {
public void actionPerformed(ActionArgs e) {
// Do stuff
// Note that any outer variables you intend to close over must be final.
}
});
handlers.get(ACTION_FROB).actionPerformed(foo);
(edit) If you want to be even more abusive, you can initialize the HashMap like so:
HashMap<Integer,String> m = new HashMap<Integer,String>() {{
put(0,"hello");
put(1,"world");
}};