[Learning-Groovy读书笔记]Groovy Design Pattern

Groovy Design Pattern

策略模式

在Groovy中,函数是一等公民,所以和Java相比,实现策略模式时更加灵活。

策略模式的例子很多。这里省略

Meta-Programming

Meta-Class

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]

Categories(静态方法工具箱)

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

Missing Methods

"按需分配"式的定义方法。通过 **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

Delegation(委托)

所谓委托:抽取其他类的Public方法接口作为本类的方法,但将方法的实现委托与其他类的实例。可以:

  1. 使用类的组合而非继承。
  2. 模拟多重继承。
  3. 践行迪米特法则(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

问题:

  1. 下面这些代码被执行时,最后 new Slary().plus(1000) 语句会返回 5000.
class Slary{ 
    int amount


    def methodMissing(String name,  args){
        println ("enter methodMissing")
        def impl = {
          this.amount += args[0]
          println  "this:$this"
          this
        }
        println "impl:$impl"
        Slary.metaClass."$name" = impl
        impl()
    }
}

def a = new Slary().plus(1000)
println "a:$a, a.amount:${a.amount}"
def b = a.plus(1000)
println "b:$b, b.amount:${b.amount}"
def c = new Slary().plus(1000)
println "c:$c, c.amount: ${c.amount}"



执行结果如下:

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

推测原因如下:

  1. println “impl:$impl” 将会执行impl Closure.
  2. 使用 Slary.metaClass."$name" = implimpl Closure 设置为 Slary的 metaClass 方法之后,设置时的this或者amount会被“冻住”到memtaClass中,所以即使我们重新创建Slary实例,调用plus时,实际使用是第一个实例。
  3. 在添加 metaClass 方法之前创建的实例,无法看到新创建的方法。所以 a.plus(1000) 实际调用的还是 methodMissing 方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值