返回介绍

1.7 委托模式

发布于 2025-01-04 00:44:54 字数 2894 浏览 0 评论 0 收藏 0

委托模式(Delegation Pattern) 对象行为(公共方法)由委托的一个或多个对象实现。

Groovy 还允许使用委托模式的传统方式,比如 用委托代替继承

1.7.1 利用 ExpandoMetaClass 实现委托模式

groovy.lang.ExpandoMetaClass 允许通过库封装来使用该模式。这能让 Groovy 效仿 Ruby 语言所用的类似库。

考虑下面这个库类:

class Delegator {
  private targetClass
  private delegate
  Delegator(targetClass, delegate) {
    this.targetClass = targetClass
    this.delegate = delegate
  }
  def delegate(String methodName) {
    delegate(methodName, methodName)
  }
  def delegate(String methodName, String asMethodName) {
    targetClass.metaClass."$asMethodName" = delegate.&"$methodName"
  }
  def delegateAll(String[] names) {
    names.each { delegate(it) }
  }
  def delegateAll(Map names) {
    names.each { k, v -> delegate(k, v) }
  }
  def delegateAll() {
    delegate.class.methods*.name.each { delegate(it) }
  }
}

将它放在类路径中,可以像上例所示的那样动态地应用委托模式。首先假设我们有以下这些类:

class Person {
  String name
}

class MortgageLender {
  def borrowAmount(amount) {
     "borrow \\$$amount"
  }
  def borrowFor(thing) {
     "buy \\$thing"
  }
}

def lender = new MortgageLender()

def delegator = new Delegator(Person, lender)

可以使用 delegator 自动地从 lender 对象处借调方法来扩展 Person 类。我们可以照原样借调方法,也可以对方法改名。

delegator.delegate 'borrowFor'
delegator.delegate 'borrowAmount', 'getMoney'

def p = new Person()

println p.borrowFor('present')   // => buy present
println p.getMoney(50)

上述代码中的第一行中,通过委托给 lender 对象,为 Person 类添加了 borrowFor 方法。第二行中,通过委托给 lender 对象的 borrowAmount 方法,为 Person 类添加了一个 getMoney 方法。

另外,我们还可以借调多个方法:

delegator.delegateAll 'borrowFor', 'borrowAmount'

这会将两种方法都添加到 Person 类上。

或者,有时我们会需要所有方法:

delegator.delegateAll()  

从而使 Person 类能够使用委托对象中的所有方法。

另外,可以利用映射标记重新命名多个方法:

delegator.delegateAll borrowAmount:'getMoney', borrowFor:'getThing'  

1.7.2 利用 @Delegate 标记实现委托模式

从 1.6 版开始,可以使用内建的基于 AST 变换的委托模式。

委托可以变得更简单:

class Person {
  def name
  @Delegate MortgageLender mortgageLender = new MortgageLender()
}

class MortgageLender {
  def borrowAmount(amount) {
     "borrow \\$$amount"
  }
  def borrowFor(thing) {
     "buy $thing"
  }
}

def p = new Person()

assert "buy present" == p.borrowFor('present')
assert "borrow \\$50" == p.borrowAmount(50)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文