在Java編程世界,有兩個設計模式又簡單、又經常使用,並且實現方式也很類似,這就是命令模式和策略模式。算法
有關這兩個模式的講解,在網絡上真是汗牛充棟,你們能夠隨便搜索一下,就是一大堆。編程
能夠簡單的說,命令模式就是對行爲或者命令的封裝,而策略模式則是對算法的封裝。對於行爲或是說命令,還有算法,在編碼的實現上都是要用到方法來實現的。設計模式
因此,咱們能夠簡單的把這兩種模式這樣理解:它們都是要對方法進行操做,像使用類和對象那樣操做,好比傳遞和循環,而在Java等面向對象的編程語言中,方法是不能獨立操做的,它必須依附於一個類和對象,而不能直接操做一個方法。基於這樣的緣由,咱們設計了命令模式和策略模式來解決上面的問題。具體的實現就是抽象出一個接口來操做這些方法,而接口的實現就是用來具體實現一個個的行爲或策略;而咱們就是經過引用接口來達到引用這些方法的目的。網絡
下面舉一個簡單的例子來講明上面的理解。好比,咱們要控制一盞燈的開關,利用命令模式能夠設計以下。閉包
咱們先抽象出一個接口來:編程語言
public interface Light {測試
public void common();編碼
}spa
這個接口是咱們可以引用開關動做的基礎,下面咱們來實現燈的開關動做:設計
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(),newLightOff()};
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,lighter,lightOff]
commons.each{
it.call()
}
運行結果爲:
light turn on...
make it lighter...
light turn off...
在上面的編碼中,咱們沒有新增任何的類,卻也實現了對燈的動做的擴展,這就是使用閉包的方便之處。
固然,咱們上面的例子都是以命令模式來說解的,其實策略模式也是同樣的道理,只不過命令模式是對行爲或動做的封裝,而策略模式是對算法的封裝,有興趣的你,不妨使用閉包來實現策略模式看看。