Groovy探索之闭包 八
?????????????????????????? Groovy探索之闭包 八
?
?
在Java编程世界,有两个设计模式又简单、又常用,而且实现方式也很相似,这就是命令模式和策略模式。 有关这两个模式的讲解,在网络上真是汗牛充栋,大家可以随便搜索一下,就是一大堆。 可以简单的说,命令模式就是对行为或者命令的封装,而策略模式则是对算法的封装。对于行为或是说命令,还有算法,在编码的实现上都是要用到方法来实现的。 所以,我们可以简单的把这两种模式这样理解:它们都是要对方法进行操作,像使用类和对象那样操作,比如传递和循环,而在Java等面向对象的编程语言中,方法是不能独立操作的,它必须依附于一个类和对象,而不能直接操作一个方法。基于这样的原因,我们设计了命令模式和策略模式来解决上面的问题。具体的实现就是抽象出一个接口来操作这些方法,而接口的实现就是用来具体实现一个个的行为或策略;而我们就是通过引用接口来达到引用这些方法的目的。 下面举一个简单的例子来说明上面的理解。比如,我们要控制一盏灯的开关,利用命令模式可以设计如下。 我们先抽象出一个接口来:
?
public interface Light { ??? ??? public void common();
?
}
?
这个接口是我们能够引用开关动作的基础,下面我们来实现灯的开关动作:
?
public class LightOn implements Light {
?
??? public void common() { ?????? System.out.println("light turn on..."); ??? }
?
}
?
上面是开灯的动作,我们接着写关灯的动作:
?
public class LightOff implements Light {
?
??? public void common() { ?????? System.out.println("light turn off..."); ??? }
?
}
?
?
接着就是对上面的抽象的使用:
?
public class LightAction {
?
??? public static void main(String[] args) { ?????? ?????? Light[] actions= new Light[]{new LightOn(),new LightOff(),new LightOn(),new LightOff()}; ?????? ?????? for(int i=0;i<actions.length;i++) ?????? { ?????????? actions[i].common(); ?????? }
?
??? }
?
}
?
运行结果为:
?
light turn on... light turn off... light turn on... light turn off...
?
通过上面的例子,可以看到,所谓命令模式,就是我们希望将形如开灯和关灯这样的动作进行组合或者传递,而开灯和关灯在代码中对应为方法,在面向对象的编程中,方法是不能直接进行组合或传递的,所以我们把开灯和关灯的方法依附于两个类“LightOn”和“LightOff”上。同时,为了方便方法之间的组合执行和传递,它们必须实现相同的接口,只有这样,“actions[i].common()”这样的语句才能正确执行。 通过了上面的分析,我们可以得出结论:在Java语言中使用命令模式和策略模式,完全是由于面向对象的语言中不能独立存在方法而导致的,同时方法也不能直接被传递,而必须依赖于类。 明白了上面的道理,我们就可以想到,如果一个语言中的方法可以直接被当作对象来使用和传递,我们就可以抛开命令模式和策略模式,而直接使用方法来操作。这就比命令模式和策略模式来得更为直接和简单易懂。 而我们的Groovy语言正是存在这样的特点,我们都知道,虽然在Groovy语言中,方法也不能直接被用来传递和使用,但是有一种方法的变形可以直接被当作对象来使用,这就是闭包。 下面,我们来看看闭包是如何实现策略模式的。首先,我们设计一个类来实现所有的方法: class Light { ??? ??? def turnOn() ??? { ?????? println 'light turn on...' ??? } ??? ??? def turnOff() ??? { ?????? println 'light turn off...' ??? }
?
}
?
?
然后,我们就可以实现命令模式了:
?
??? ? def light = new Light() ??? ? ??? ? def lightOn = light.&turnOn ??? ? ??? ? def lightOff = light.&turnOff ??? ? ??? ? def commons = [lightOn,lightOff,lightOn,lightOff] ??? ? ??? ? commons.each{ ?????? ? it.call() ? }
?
运行结果为:
?
light turn on... light turn off... light turn on... light turn off...
?
可以看到,上面的代码比起Java语言中的命令模式实现起来要简单得多,但功能却是一样的。 还有,模式的一个重要功能是它良好的扩展性。上面的命令模式就拥有良好的扩展性,比如我们希望增加一个方法来调节灯的亮度,使得更亮一些。命令模式在新增一个方法的时候,不会去修改已经写好的类,这样会导致已经写好的代码需要重新测试。我们只需增加一个新的类:
?
public class Lighter implements Light {
?
??? public void common() { ?????? ?????? System.out.println("make it lighter..."); ?????? ??? }
?
}
?
?
增加了新的类以后,我们当然就可以照常使用它了:
?
?
?????? Light[] actions= new Light[]{new LightOn(),new Lighter(),new LightOff()}; ?????? ?????? for(int i=0;i<actions.length;i++) ?????? { ?????????? actions[i].common(); ?????? } ???
?
运行结果为:
?
light turn on... make it lighter... light turn off...
?
那么,我们在Groovy语言中使用闭包来实现的命令模式是否也拥有良好的扩展性呢?我们的回答是:当然,它也有良好的扩展性。下面我们来看闭包的命令模式的扩展性的例子。 首先,我们可以新增一个类来实现这个新的行为:
?
class Lighter { ??? ??? def turnLighter() ??? { ?????? println 'make it lighter...' ??? }
?
}
?
这是一个新的类,当然没有修改到原来的类“Light”。下面,我们来看怎么使用它:
?
??? ? ?????? def light = new Light() ??? ? ??? ? def lightOn = light.&turnOn ??? ? ??? ? def lightOff = light.&turnOff ??? ? ??? ? def l = new Lighter() ?????? ?????? def lighter = l.&turnLighter ??? ? ??? ? def commons = [lightOn,lighter,lightOff] ??? ? ??? ? commons.each{ ?????? ? it.call() ??? ? } ???
?
?
运行结果为:
?
light turn on... make it lighter... light turn off...
?
我们可以看到,在Groovy语言中,使用闭包实现的命令模式扩展起来也是一样的方便,它甚至可以更方便,我们可以不用新增类,即“Lighter”都不需要。请看下面的编码: ??? ? ?????? def light = new Light1() ??? ? ??? ? def lightOn = light.&turnOn ??? ? ??? ? def lightOff = light.&turnOff
?
?????? def lighter = { ?????????? println 'make it lighter...' ?????? } ??? ? ??? ? def commons = [lightOn,lightOff] ??? ? ??? ? commons.each{ ?????? ? it.call() ??? ? } ???
?
运行结果为:
?
light turn on... make it lighter... light turn off...
?
?
在上面的编码中,我们没有新增任何的类,却也实现了对灯的动作的扩展,这就是使用闭包的方便之处。
?
当然,我们上面的例子都是以命令模式来讲解的,其实策略模式也是一样的道理,只不过命令模式是对行为或动作的封装,而策略模式是对算法的封装,有兴趣的你,不妨使用闭包来实现策略模式看看。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |