Java中的函数数组?
也许我在C语言中想得太多了,但我没有看到一个解决方案,如何在java中正确地解决这个问题。 我从服务器收到一个响应,该响应发送一个字符串,如下所示:Java中的函数数组?,java,jump-table,Java,Jump Table,也许我在C语言中想得太多了,但我没有看到一个解决方案,如何在java中正确地解决这个问题。 我从服务器收到一个响应,该响应发送一个字符串,如下所示: command params <xml...> 命令参数 客户端接收该字符串并提取命令。现在我想调用一个知道如何处理命令的函数。在C方面,解决方案是显而易见的。我用命令名和相关函数点实现了一个数组,因此我可以简单地循环数组并调用函数 在Java上也有这样做的方法吗?我不知道是否可以根据名称调用函数。因此,目前我看到以下选项: 执行一
command params <xml...>
命令参数
客户端接收该字符串并提取命令。现在我想调用一个知道如何处理命令的函数。在C方面,解决方案是显而易见的。我用命令名和相关函数点实现了一个数组,因此我可以简单地循环数组并调用函数
在Java上也有这样做的方法吗?我不知道是否可以根据名称调用函数。因此,目前我看到以下选项:
if(command.euqals(command)
if语句不是最好的IMO,但至少它允许编译器错误和类型检查。使用反射至少更优雅,因为我可以更容易地循环和扩展它,但当然,这意味着如果我键入错误的名称,我只能看到运行时错误。你的第二个想法是惯用的。使用
映射来存储command名称和相应的代码,然后commands.get(commandName).run()
执行一个命令
不要害怕创建类!这可能会让你的代码一开始就更加冗长,但是编写一个类和不再担心它要比使用开关或if…else if…
做同样的事情容易得多。如果你的命令比单个方法更复杂(可能toString()
,undo()
…),您会越来越高兴您使用了多态性而不是条件。我过去曾使用以下方法解决过此类问题,它可能适用于您的情况:
具有标准界面:
public interface Executable {
public String getCommandName();
public void execute(String[] params, String xml);
}
和x实现的数量:
public class SaveExecutable implements Executable {
private static final String COMMAND_NAME = "SAVE";
public String getCommandName() {
return COMMAND_NAME;
}
public void execute(String[] params, String xml) {
...
}
}
然后将实现存储在HashMap中进行查找:
HashMap<String, Executor> executors = new HashMap<>();
executors.put("SAVE", new SaveExecutable());
如果只想有一个文件,可以使用enum
创建
试着这样做:
public class Command {
public enum CommandName {
UNDO,
PRINT,
RUN
}
public static void execute(String command, String[] params, String xml) {
try {
CommandName cname = CommandName.valueOf(command);
switch (cname) {
case UNDO:
undo (params, xml);
break;
case PRINT:
//
break;
}
} catch (IllegalArgumentException iae) {
// Unknown command
}
}
public static void undo (String[] params, String xml) {
// ....
}
}
运行以下命令:
Command.execute(command, params, xml);
我最近看到一个函数技巧,虽然很简单,但非常有效:“用另一个函数包装”一个函数或一组函数
下面是我为展示这一技巧而编写的代码示例。
我的示例只为一个命令提供一个函数,但如果需要,它可以很容易地扩展为返回的一组函数(因此包含可以使用的Guava Mutlimap类型)…我返回一个可选的,因此当命令不匹配时,它“安全地”返回null;Contact和ContacUnit都是域类型,它们都扩展了一个组织类型……这样下面的代码就有意义了
package com.xxx.component;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.xxx.domain.Contact;
import com.xxx.domain.ContactUnit;
import com.xxx.domain.Organization;
import java.util.Optional;
import java.util.function.Function;
/**
* This serves up the functions used for the domain
* to validate itself.
* Created by beezerbutt on 06/04/2017.
*/
public class MapSetDomainFunctionFactory {
public static final Function<String, Optional<Organization>> toContactFromCwid = s-> Optional.ofNullable(s).map(Contact::new);
public static final Function<String, Optional<Organization>> toContactUnitFromKey = s-> Optional.ofNullable(s).map(ContactUnit::new);
public static final Function<String, Function<String, Optional<Organization>>> commandToFunctions = command -> {
if (command.equalsIgnoreCase("toContactFromCwid")) {
return MapSetDomainFunctionFactory.toContactFromCwid;
} else {
return null;
}
};
}
下面是我为证明代码有效而运行的Spock测试的快照:
我觉得有点混乱,因为我必须创建很多类来执行一个任务,它甚至不能自己执行,相反它必须更新GUI等等。另一方面,也许这不是一个坏主意,我必须看看它对GUI代码有什么影响。我一点也不认为这是混乱的;它是pol的基石ymorphism!我越是考虑这种方法,我就越喜欢它。我最初的想法是我会有数百个小类,但在重新考虑参数后,它并没有那么糟糕,它肯定有你提到的优点。现在你可以创建匿名类就更好了。new Command(){run(){/*process command*/}
-这可以是一个command
数组,其中它是一个接口类。请记住,Java枚举可以有方法-您可以声明一个抽象doExecute
,而不是开关
只需执行cname.doExecute()
。
package com.xxx.component;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.xxx.domain.Contact;
import com.xxx.domain.ContactUnit;
import com.xxx.domain.Organization;
import java.util.Optional;
import java.util.function.Function;
/**
* This serves up the functions used for the domain
* to validate itself.
* Created by beezerbutt on 06/04/2017.
*/
public class MapSetDomainFunctionFactory {
public static final Function<String, Optional<Organization>> toContactFromCwid = s-> Optional.ofNullable(s).map(Contact::new);
public static final Function<String, Optional<Organization>> toContactUnitFromKey = s-> Optional.ofNullable(s).map(ContactUnit::new);
public static final Function<String, Function<String, Optional<Organization>>> commandToFunctions = command -> {
if (command.equalsIgnoreCase("toContactFromCwid")) {
return MapSetDomainFunctionFactory.toContactFromCwid;
} else {
return null;
}
};
}
/**
* Created by beezerbutt on 06/04/2017.
*/
public class Contact implements Organization {
}
public class ContactUnit implements Organization {
}
public interface Organization {
}