java—使用循环根据找到的字符串调用不同的方法

oiopk7p5  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(516)

我正在使用pircbotx提供的侦听器(https://github.com/pircbotx/pircbotx/wiki/documentation)为了检测在twitch chat中何时发现命令,我尝试使用不同的方法,具体取决于调用哪个命令(格式是!命令)。使用的类:侦听器、命令。
命令存储在由一个字符串(名称)组成的命令对象数组中。每个command对象最终将使用自己的方法,该方法将在command类中定义。listeners对象示例化后将立即将数组的每个元素放入哈希表(命令)。
当侦听器检测到消息时,它将使用本地字符串变量(msg)存储。当这种情况发生时,一个循环遍历命令对象数组,然后。。。。应该调用与特定对象对应的方法,在本例中是command.adddeath()。那就是我被困的地方。
我以前为我的听众使用了一堆if语句,但是当有一堆命令时,事情会变得非常非常混乱。如果我的代码块中的格式很奇怪,请提前道歉,我对使用stackverflow非常陌生,而且我也是一个java新手,在学习的过程中一直在学习。再看一遍代码后,我似乎并不需要哈希表,但我把它放在那里,以防万一你们对如何处理它们有更好的想法。

public class Listeners {

String name;
String message;    
private static MessageEvent event;
Command [] commandNames = {new Command("!clearchat", new Command("!addDeath")}; 
Hashtable<String, Command> commands = new Hashtable<String, Command>();

 public Listeners() {
    for (int i = 0; i < commandNames.length; i++) {
        commands.put(commandNames[i].name, new Command(commandNames[i].name));
    }   

    if (event.getMessage() != null) {
        String msg = event.getMessage();
        for (int x = 0; x < commandNames.length; x++ ) {
            if (msg.startsWith(commandNames[x].name)) {
                // call Command method here 
            }
        }
    }   
}

下面是命令类:

public class Command {

String name;

public Command(String name) {
        this.name = name;
}

public static void addDeath() {
    DeathCounter.addDeath();
    Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
} 
}
hlswsv35

hlswsv351#

您可以使用命令界面:

public interface Command {
    public abstract void execute();
}

然后让您的命令实现接口:

public class DeathCommand implements Command {
    @Override
    public void execute() {
        DeathCounter.addDeath();
        Listeners.sendMessage("Death Counter: " + DeathCounter.getDeaths());
    }
}

在侦听器类中,将命令字符串Map到相应命令的示例:

public class Listeners {

    String name;
    String message;
    private static MessageEvent event;
    static Map<String, Command> commands = new HashMap<>();

    static {
        commands.put("!addDeath", new DeathCommand());
    }

    public Listeners() {
        if (event.getMessage() != null) {
            String msg = event.getMessage();
            Optional<String> key = commands.keySet().stream().filter(k -> msg.startsWith(k)).findFirst();
            key.ifPresent(s -> commands.get(s).execute());
        }
    }
}

我用一个hashmap替换了您的hashtable,这个hashmap在大多数方面都更好(但使用方式相同)。
我有点怀疑是否将map作为一个静态成员,但是由于我不熟悉您的用例,所以我保留了这一点。
编辑
所有java类都有一个默认的构造函数(没有参数),除非您编写自己的构造函数(如果仍然需要,您必须自己编写默认的构造函数)。接口没有构造函数,因为它们不能直接示例化。它们只指定实现类必须具有的方法。这允许您拥有接口类型的引用(命名字段/变量),并且能够在不知道或不必知道它是哪个实现的情况下调用方法。
例子:

Command com = new DeathCommand();
com.execute(); // <- this will run the execute() code in the DeathCommand class
Command com2 = new SomeOtherCommand();
com2.execute(); // <- this will run the execute() code in the SomeOtherCommand class

以上命令代码已完成。没有别的了。至于deathcommand和其他实现,您需要添加所需的代码。
每个类和接口都位于自己的文件中,文件名为类型:

Command.java
DeathCommand.java

关于hashtable和hashmap。我应该说最好使用map及其实现。如果您需要线程安全,请使用agilob指出的concurrenthashmap,因为常规hashmap不是线程安全的。

相关问题