Groovy探索之Map与DSL
???????????????????????????? Groovy探索之Map与DSL
?
?
在Java语言编程中,从Java5开始引入了可变参数的概念;引入可变参数的目的,是为了解决形如下面代码的编码冗余。 public class VarArgument { ??? ??? private int a,b,c,d; ??? ??? ??? private void p() ??? { ?????? System.out.println(a+","+b+","+c+","+d); ??? } ??? ??? public void foo(int a) ??? { ?????? this.a = a; ?????? p(); ??? } ??? ??? public void foo(int a,int b) ??? { ?????? this.a = a; ?????? this.b = b; ?????? ?????? p(); ??? } ??? ??? public void foo(int a,int b,int c) ??? { ?????? this.a = a; ?????? this.b = b; ?????? this.c = c; ?????? ?????? p(); ??? } ??? ??? public void foo(int a,int c,int d) ??? { ?????? this.a = a; ?????? this.b = b; ?????? this.c = c; ?????? this.d = d; ?????? ?????? p(); ??? } ??? ??? public static void main(String[] args) { ?????? ?????? VarArgument va = new VarArgument(); ?????? ?????? va.foo(1,4);
?
??? }
?
}
?
?
上面的代码中,是一个面向对象编程中的常用的方法重载,目的是为了解决“foo”方法输入参数的个数是可以变化的问题,也就是可变参数的问题。我们可以看到,利用方法重载来解决可变参数的问题,我们需要写出多个方法来做同一件事情,这使得我们的编码效率大大降低。 为了提高编码效率,我们从Java5开始引入了可变参数的概念,通过可变参数上面的代码可以写成下面的样子: public class VarArgument { ??? ??? private int a,d; ??? ??? public void foo(int... nums) ??? { ?????? int len = nums.length; ?????? ?????? if(len>0) a = nums[0]; ?????? ?????? if(len>1) b = nums[1]; ?????? ?????? if(len>2) c = nums[2]; ?????? ?????? if(len>3) d = nums[3]; ?????? ?????? //todo ?????? ?????? System.out.println(a+","+d); ??? } ??? ??? public static void main(String[] args) { ?????? ?????? VarArgument va = new VarArgument(); ?????? ?????? va.foo(1,4);
?
??? }
?
}
?
可以看出,随着Java5引入的可变参数概念,的确使得我们的编码量大大减轻,使得我们朝着敏捷编程的方向在前进。但是,可变参数的引入,仍然有以下三个问题没有解决:一是,可读性的问题,作为VarArgument类的使用者,我们不知道“va.foo(1,4)”中的“1”和“4”代表的含义。二是,参数顺序的问题,比如我们想将1赋给a,4赋给b,当然只能严格写成“va.foo(1,4)”,而不能写成“va.foo(4,1)”。三是,灵活性不足,比如,我们只想给a赋值1,c赋值3,我们就得写成这样的“va.foo(1,3)”,而不能写成这样“va.foo(1,3)”。
?
为了解决上面的问题,我们在Groovy语言中来使用Map对象作为“foo”方法的参数,请看下面的示例: class Testor4 { ??? ??? private int a,b,c,d ??? ??? def foo(Map map) ??? { ?????? this.a = map['a']?map['a']:a ?????? this.b = map['b']?map['b']:b ?????? this.c = map['c']?map['c']:c ?????? this.d = map['d']?map['d']:d ?????? ?????? //todo ?????? ?????? println "$a,$b,$c,$d" ??? }
?
? static void main(args) { ??? ? ??? ? def t = new Testor4() ??? ? ?????? t.foo([a:1,b:4]) ? }
?
}
?
?
可以看到,引入了Map作为参数,我们在Java编程中的可变参数所没有解决的三个问题都得到了解决。 你可能会说,这没有什么啊,Java语言也可以使用Map作为参数啊。是的,Java语言的确可以使用Map作为参数,但Groovy语言对Map参数所做的如下简化,就是Java语言所不及的了。
?
def t = new Testor4()
?
?????? t.foo(a:1,b:4) ???
?
看到了吗?作为“foo”方法的使用者,我们可以完全不知道我们输入的参数是Map类型的,我们只知道把我需要给方法的两个参数a和b使用“t.foo(a:1,b:4)”的方式给方法;如果我们只想给a和c赋值,则可以使用这样的形式“t.foo(a:1,c:3)”。这真的是在可读性和敏捷性上大大提高。
?
看到了上面的代码,我们立刻会想起我们在GroovyBean中是如何初始化一个对象的。比如有如下一个GroovyBean:
?
class Person { ??? String id ??? String name ??? String age }
?
?
我们会使用如下的方式来初始化它:
?
?????? def person = new Person(name:'Tom',age:23) ???
?
现在我们就可以知道其中的奥秘了。 正是因为在Groovy语言中使用Map对象作为输入参数大大增强了代码的可读性,我们把它作为DSL编程实现的一种方式。
?
下面,我们使用一个求两点之间的距离的方法来演示使用Map对象作为输入参数的DSL编程方式的例子。
?
?
class Testor5 { ??? ??? def length(Map map) ??? { ?????? ?????? def fx = map['x1'] ?????? ?????? def fy = map['y1'] ?????? ?????? def tx = map['x2'] ?????? ?????? def ty = map['y2'] ?????? ?????? return Math.sqrt((fx-tx)*(fx-tx)+(fy-ty)*(fy-ty)) ??? }
?
? static void main(args) { ??? ? ??? ? def mc = new ExpandoMetaClass(Integer.class,true) ?????? ?????? mc.getM << ?????? { ?????????? -> ????????????? delegate as float ?????? } ?????? ?????? mc.getCm << ?????? { ?????????? -> ????????????? def cm = delegate as float ????????????? cm/100 ?????? } ?????? ?????? mc.initialize() ?????? ??? ? ??? ? def t = new Testor5() ??? ? ??? ? println t.length(x1:1.m,y1:200.cm,x2:4.m,y2:500.cm) ??? ? ???
?
? }
?
}
?
?
在上面的例子中,我们使用数学坐标来表达点,比如“x1:1.m,y1:200.cm”代表起点,而“1.m”代表1米的地方,“200.cm”代表200厘米。“x2:4.m,y2:500.cm”代表终点的坐标。这种表达法的可读性就非常强,对于“1.m”和“200.cm”这样的表达式,我们在《Groovy探索之运算符的重载 二》里详细的讲过,没看过的可以点击http://blog.csdn.net/hivon/archive/2008/07/15/2651693.aspx。 可以看到,“length(x1:1.m,y2:500.cm)”用来表达两点(x1:1.m,y1:200.cm)和(x2:4.m,y2:500.cm)之间的距离,这样的可读性比较好,而且使用Map作为输入参数,实现起来也比较简单。
?
总之,在Groovy语言中使用Map作为输入参数,给我们带来编码的可读性,可以作为DSL的一种实现方式。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |