Reputation: 2922
I have a Java bot running based on the PircBotX framework. An IRC bot simply replies on commands. So now I have a list of static strings e.g.; !weather
, !lastseen
and the likes in my Main.java
file.
For each command I add I create a new static string and I compare each incoming message if it starts with any of the defined commands.
Pseudocode
Receive message `m`
if m matches !x
-> do handleX()
if m matches !y
-> do handleY()
This is basicly a very large if test.
What I would like to do is create some sort of skeleton class that perhaps implements an interface and defines on which command it should act and a body that defines the code it should execute. Something I'm thinking of is shown below:
public class XkcdHandler implements CommandHandlerInterface
{
public String getCommand()
{
return "!xkcd";
}
public void HandleCommand(String[] args, Channel ircChannel)
{
// Get XKCD..
ircChannel.send("The XKCD for today is ..");
}
}
With such a class I could simply add a new class and be done with it. Now I have to add the command, add the if test in the list, and add the method to the Main.java class. It is just not a nice example of software architecture.
Is there a way that I could create something that automatically loads these classes (or instances of those classes), and then just call something like invokeMatchingCommand()
? This code could then iterate a list of loaded commands and invoke HandleCommand
on the matching instance.
Update
With the answer of BalckEye in mind I figured I could load all classes that are found in a package (i.e., Modules
), instantiate them and store them in a list. This way I could handle each message as shown in his answer (i.e., iterate the list and execute the class method for each matching command).
However, it seems, according to this thread, that it's not really viable to do. At this point I'm having a look at classloaders, perhaps that would be a viable solution.
Upvotes: 0
Views: 125
Reputation: 807
There are several ways I think. You can just use a Map with the command as the key and an interface which executes your code as the value. Something like this:
Map<String, CommandInterface> commands = new ....
and then use the map like this:
CommandInterface cmd = commands.get(command);
if(cmd != null) {
cmd.execute();
}
Upvotes: 1
Reputation:
You are looking for the static block, for instance:
class main {
private static List<CommandHandlerInterface> modules = new ArrayList<...>();
static { // gets called when a static member gets accessed for the first time (once per class)
modules.add(new WeatherCommand());
// etc.
}
// method here which iterates over modules and checks
}
Upvotes: 0