Christophe De Troyer
Christophe De Troyer

Reputation: 2922

Create modules Java

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

Answers (2)

Martin Fernau
Martin Fernau

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

user4335475
user4335475

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

Related Questions