我有一组特定的操作,我希望能够按名称动态访问。
如果我使用JavaScript,我会将它们表示在字典中,其中操作的名称为键,操作函数为值。
然后,例如,我可以询问用户操作的名称,显示操作的结果(如果存在),并显示错误消息(如果不存在),如下所示:
var operations = {
addition: function(a, b) { return a + b; },
subtraction: function(a, b) { return a - b; },
multiplication: function(a, b) { return a * b; }
// etc.
};
var a = 4, b = 7;
var opName = prompt("Enter operation name:");
if (opName in operations) {
alert("Result: " + operations[opName](a, b));
} else {
alert("The operation '" + opName + "' does not exist.");
}
我如何用Java做同样的事情?我可以有一个Set<String>
的操作名称和一个使用带有每个操作大小写的开关的函数,但是这需要我重复每个操作名称两次,这使得代码更加脆弱,编写和维护更加繁琐
对于Java中的这类事情,是否有一个相当简洁的DRY模式?
答案 0 :(得分:3)
这在Java 8中使用lambdas非常简洁:
Map<String, BinaryOperator<Integer>> operators = new TreeMap<>();
operators.put("add", (n1, n2) -> n1 + n2);
operators.put("minus", (n1, n2) -> n1 - n2);
if (operators.containsKey(opName)) {
return operators.get(opName).apply(n1, n2);
}
但我从你的评论中得知,这不是一个选择。另一种方法是使用枚举来包含您的操作,以便您可以在一个地方添加新操作:
enum Operation {
PLUS {
public int operate(int arg1, int arg2) {
return arg1 + arg2;
}
},
MINUS {
public int operate(int arg1, int arg2) {
return arg1 - arg2;
}
},
...
abstract public int operate(int arg1, int arg2);
}
for (operation: Operations.values()) {
if (operation.name().equals(opName))
System.out.println("result = " + operation.operate(arg1, arg2));
return;
}
}
System.out.println("The Operation " + opName + " does not exist");
答案 1 :(得分:2)
true
答案 2 :(得分:1)
您可以在不使用Java8的情况下在Java中执行相同的操作:
public interface Operation<T,R> {
R perform(T... args);
}
public void test() {
Map<String, Operation> operations = new HashMap<String, Operation>() {
{
this.put("addition", new Operation<Integer, Integer>() {
public Integer perform(Integer... args) {
return args[0] + args[1];
}});
}
};
String operation = "";
Integer a = 1;
Integer b = 1;
if (operations.containsKey(operation)) {
System.out.println("Result: " + operations.get(operation).perform(a, b));
} else {
System.out.println("The operation '" + operation + "' does not exist.");
}
}
如果您愿意,也可以将该匿名类移动到单独的文件中。
如果您需要不同类型的参数,则必须使用泛型或将参数类型更改为Object
,然后进行强制转换。不是很漂亮,但这是静态打字的代价。
如果您想在同一个地图中存储不同类型的操作,编译器也会向您发出警告(使用原始Operation
),但这里没什么可做的。一种方法是为不同类型制作几张地图。