我有一个switch语句,将String
与String
的集合进行比较,其中每个匹配调用不同的方法。
switch(((Operation) expr.getData()).getValue()){
case "+":
return add(expr.getNext());
case "car":
return car(expr.getNext());
case "cdr":
return cdr(expr.getNext());
case "cons":
return cons(expr.getNext(), expr.getNext().getNext());
case "quote":
return quote(expr.getNext());
case "define":
handleDefine(expr.getNext());
break;
default:
return null;
}
然而,对我而言,使用HashMap
链接到包含Operation
的{{1}}和参数数量的Method
,这听起来更优雅,更有效。所以我可以将每个方法都改为HashMap
:
nameToOperation.put("+", new Operation("+", 1, Driver.class.getMethod("add")));
nameToOperation.put("car", new Operation("car", 1, Driver.class.getMethod("car")));
因此,将有N个不同的Operation类实例,每个实例包含String,Method和参数数量
然后我可以使用与此类似的东西调用该方法(我知道这不是你使用invoke的方式):
Operation op = ((Operation) expr.getData())
if(op.getNumPars() == 1)
return(op.getMethod().invoke(expr.getNext()));
else
return(op.getMethod().invoke(expr.getNext(), expr.getNext().getNext()));
然而,我仍然不完全喜欢这种解决方案,因为我正在失去类型安全性,但它仍然看起来不那么好。我在stackoverflow上看到的另一个例子看起来相当优雅但我不完全理解的是最佳答案的第一个解决方案:How to call a method stored in a HashMap? (Java)
Stackoverflow上的每个人都认为最好的解决方案是什么?
编辑:万一有人搜索这个并且想知道我的解决方案,我让每个操作如Add,Car,Cdr都有他们自己的实现Command
的类。然后我不得不让我的大多数方法都是静态的,我认为它们本质上都是静态的。这似乎比原始案例陈述更优雅。
答案 0 :(得分:1)
"The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that know how to perform it. And this advantage must be kept. There are implementations of this design pattern in which the invoker is aware of the concrete commands classes. This is wrong making the implementation more tightly coupled. The invoker should be aware only about the abstract command class"
Map <character,Command>
答案 1 :(得分:0)
看起来你正在尝试编写一个Scheme解释器。在这种情况下,无论如何你都需要一张地图,因为你需要存储所有用户定义的值和函数。 当用户写例如(定义(添加b)(+ a b)),使用“add”作为键将函数存储在地图中。 但是你的函数应该使用列表作为输入,即每个函数只有一个参数是一个列表。在Scheme中,所有表达式都是顺序列表。通常,Scheme解释器由读者和评估者组成。读者将代码转换为一堆嵌套列表。 所以基本上“(define(add a b)(+ a b))”可以转换成类似于此的列表结构。
List<Object> list = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list2.add("add"); list2.add("a"); list2.add("b");
List<Object> list3 = new ArrayList<Object>();
list3.add("+"); list3.add("a"); list3.add("b");
list.add("define"); list.add(list1); list.add(list2);
当然,您的代码实际上并不像这样,而是通过解析输入代码的递归方法构建列表。
这些列表不仅包含字符串btw。它们还包含数字和布尔值。像这样的嵌套列表是抽象语法树(AST)的最简单形式。由于Scheme的语法比大多数其他语言的语法简单得多,因此非常简单的列表结构足以存储已解析的代码。
然后,评估者处理这些列表。 要评估列表,首先递归计算列表中的每个元素,然后将第一个元素应用于列表的其余部分。因此,第一个元素必须是用户定义的函数或内置命令,例如“定义”。