在Groovy中,函数是一等公民,所以和Java相比,实现策略模式时更加灵活。
策略模式的例子很多。这里省略
Groovy可以通过"metaClass"属性来动态的为既有的Class添加属性或者方法。
注意:不可与@CompileStatic or @TypeChecked 联用。
String.metaClass.generator = "groovy" String.metaClass.words = { -> split(/ +/)} println "I like the groovy".generator println "I like the groovy".words()执行结果如下:
groovy [I, like, the, groovy]Category时Groovy提供的另一种扩充既有的Class,添加功能的方法。可以把Category想象成可以扩充既有Class的工具箱, 这些工具是一系列的静态方法,static 功能(扩充对象)。 当我们想使用这些工具时可以通过 use(category){} 打开这些工具箱。 例如:
class Slary{ int amount Slary plus(Slary s){ amount += s.amount this } Slary plus(Expend s){ amount -= s.amount this } } class Expend{ int amount} class SlaryCategory{ static Slary getAsSlary(Integer self) { new Slary(amount: self) } static Expend getAsExpend(Integer self) { new Expend(amount: self) } } use(SlaryCategory){ def balance = 300.asSlary + 100.asSlary + 50.asExpend println balance.amount }执行结果如下:
350"按需分配"式的定义方法。通过 **def methodMissing(String name, args) ** 捕捉对于不存在的方法调用。可在该方法中定义方法并且执行。
class Slary{ int amount def someMethod(args){ println "this:$this" println "this.amount: ${this.amount}" println "amount: $amount" amount += args } def methodMissing(String name, args){ println "MethodMissing:$name" def method = Slary.methods.find{ it.name === 'someMethod'} Slary.metaClass."$name" = method println "${name}(${args})" return method.invoke(this, args) } } def aSlary = new Slary() def a = aSlary.plus(1000) println aSlary println a def bSlary = new Slary() println bSlary def c =bSlary.plus(1000) println c执行结果如下:
MethodMissing:plus plus([1000]) this:Slary@26d77d18 this.amount: 0 amount: 0 Slary@26d77d18 1000 Slary@5ed9bf80 MethodMissing:plus plus([1000]) this:Slary@5ed9bf80 this.amount: 0 amount: 0 1000所谓委托:抽取其他类的Public方法接口作为本类的方法,但将方法的实现委托与其他类的实例。可以:
使用类的组合而非继承。模拟多重继承。践行迪米特法则(Law ofDemeter,LoD)例如:
class Tank{ def runOnRoad(){println "As tank, can run on the road"} } class Boat { def sailOnWater(){println "As boat, can sail on the water"} } class AmphibiousTank { @Delegate final Tank tank @Delegate final Boat boat public AmphibiousTank(Tank tank, Boat boat) { this.tank = tank this.boat = boat } public AmphibiousTank() { this.tank = new Tank() this.boat = new Boat() } } def amphibiousTank = new AmphibiousTank() amphibiousTank.runOnRoad() amphibiousTank.sailOnWater()执行结果如下:
As tank, can run on the road As boat, can sail on the water执行结果如下:
enter methodMissing this:Slary@7717ced9 impl: this:Slary@7717ced9 a:Slary@7717ced9, a.amount:2000 enter methodMissing this:Slary@7717ced9 impl: this:Slary@7717ced9 b:Slary@7717ced9, b.amount:4000 this:Slary@7717ced9 c:Slary@7717ced9, c.amount: 5000推测原因如下:
println “impl:$impl” 将会执行impl Closure.使用 Slary.metaClass."$name" = impl 将 impl Closure 设置为 Slary的 metaClass 方法之后,设置时的this或者amount会被“冻住”到memtaClass中,所以即使我们重新创建Slary实例,调用plus时,实际使用是第一个实例。在添加 metaClass 方法之前创建的实例,无法看到新创建的方法。所以 a.plus(1000) 实际调用的还是 methodMissing 方法。