Groovy探索之Delegate模式 一

本文探讨了委派模式在Groovy语言中的应用,对比了委派与继承的区别,并通过实例展示了如何使用委派实现更灵活的对象扩展。
Groovy探索之Delegate模式 一
Delegate即是委派的意思。在Java语言中,很少提到委派或者委派模式,即使用到了也不说,这是因为Java语言的特点,实现起委派来相当的繁琐,而且只能适用于一些简单的场合。
但现实的需求是,由于敏捷编程的兴起,重构技术也得到了大家的广泛使用;要使用重构,其中的一个重要原则是:使用组合代替聚合,这样才能方便重构。使用组合,最终是要使用到委派技术了。同时,我们经常有这样的一些需求,我们只想继承一个类的部分功能,而另外一部分功能是我们不想要、甚至是对我们有害的功能,这时候,我们只能使用委派技术,而不能使用继承了。
基于上面的一些分析,我们知道,继承和委派技术都能扩展一个类,使它拥有另外一个类的部分或者全部功能。但委派技术更为灵活,它可以使得一个类可以全部或部分的扩展得到另一个类的功能,而继承只能是全盘接收。
说了这么多,您可能要说了,我想看一些例子,或者你举出一些例子来证明你的观点啊。这正是下面要做的事。
比方说,有下面的一个简单类:
class Foo {
deftest()
{
println'have a test'
}
def foo()
{
println'foo...'
}
}
现在有一个新的类要实现它的全部功能,即“test”和“foo”方法。当然,我们首先想到的是继承:
class FooSon extends Foo{
def testAgain()
{
println'test it again'
}
}
这样,我们就可以在FooSon中使用Foo的功能了,比如:
def foo = new FooSon()
foo.test()
foo.foo()
foo.testAgain()
它的运行结果为:
have a test
foo...
test it again
这样的继承无疑是完美的,子类不用写太多代码,就完全实现了父类的功能。但它最明显的缺点是,如果我有这样的需求,我只想在子类中要Foo类的“test”方法,不想要“foo”方法,在这里继承能办到吗?
如果您的答案是否定的,请您跟着我往下看。
下面,我将使用委派技术来产生一个新类,同样继承Foo类的所有方法:
class Foo2 {
private delegate = new Foo()
deftest()
{
this.delegate.test()
}
def foo()
{
this.delegate.foo()
}
def testAgain()
{
println'test it again'
}
}
通过这个例子,您可以看到,所谓“委派”的意思是:一个类要实现的功能,比如Foo2类要实现的“test”和“foo”方法,但它并未真正去实现这些功能,而是把这些功能委派给另一个类去实现,如Foo2类的“test”和“foo”方法,实际上是交给Foo类去实现了。
可以测试一下上面的例子:
def foo = new Foo2()
foo.test()
foo.foo()
foo.testAgain()
运行结果为:
have a test
foo...
test it again
当然,我还记得上面提出来的需求,新的类只想实现Foo类的“test”方法,不想要“foo”方法。使用委派技术就很好实现了:
class Foo2 {
private delegate = new Foo()
deftest()
{
this.delegate.test()
}
def testAgain()
{
println'test it again'
}
}
看了上面的例子,您可能会说,委派技术很简单,也很好理解,但就是实现起来太繁琐了,我要想在子类中实现父类的方法,非得在子类中把这些方法重写一遍不可,远远没有继承来得方便。是的,这就是在Java语言中很少提到委派技术的原因。
但是,我们应该知道的是,Groovy语言是基于Java语言的,这使得它必定有超过Java语言之处,而对委派技术的动态实现正是Groovy语言动态的一个重要方面。下面,我将举出一个例子来实现上面的功能的动态委派技术。
class Foo3 {
private delegate = new Foo()
def invokeMethod(String name,Object args)
{
this.delegate.invokeMethod(name,args)
}
def testAgain()
{
println'test it again'
}
}
是了,我们又通过“invokeMethod”方法来实现动态委派技术,我已经记不清“invokeMethod”方法实现了我们的多少功能。
一个“invokeMethod”方法,就不管你要实现父类的多少功能,统统通过这一个方法就能实现了。下面来测试一下:
def foo = new Foo3()
foo.test()
foo.foo()
foo.testAgain()
结果为:
have a test
foo...
test it again
如果你在动态实现中,不想要父类的“foo”方法,也是可以实现的:
class Foo3 {
private delegate = new Foo()
def invokeMethod(String name,Object args)
{
if(name != 'foo')
{
this.delegate.invokeMethod(name,args)
}
}
def testAgain()
{
println'test it again'
}
}
值得注意的是,Groovy语言还有很多其他的方法来实现动态委派,这将是《Groovy探索之Delegate模式二》及《三》中要谈到的。
Groovy语言中,delegate个关键字,用于指定个对象来执行闭包内部的方法调用。当在闭包内部调用个方法时,如果该方法没有在闭包中定义,Groovy会自动将该方法调用委托给delegate对象来执行。delegate关键字允许我们在闭包内部使用外部对象的方法,而不需要显式地引用该对象。 使用delegate关键字可以简化代码,并提高代码的可读性和可维护性。通过指定delegate对象,我们可以在闭包中轻松地调用该对象的方法,而无需在闭包内部编写冗长的调用代码。这使得代码更加简洁,同时也减少了代码中的重复性。 在实际使用中,delegate关键字的用法非常灵活。可以根据实际需求来决定委托给哪个对象执行方法调用。这样,我们可以根据具体情况选择不同的delegate对象,以实现不同的功能。 在Groovy中,还有其他些相关的关键字,比如this、owner等。this关键字指的是当前闭包的实例,而owner关键字指的是持有当前闭包的对象。这些关键字与delegate关键字起使用,可以更好地控制闭包的执行行为。 总之,delegate关键字在Groovy语言中起到了简化代码、提高可读性和可维护性的作用。通过委托给指定的对象执行方法调用,我们可以轻松地在闭包内部使用外部对象的方法,从而实现更加灵活和高效的编程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Groovy探索delegate关键字 (1)](https://blog.youkuaiyun.com/hivon/article/details/3156040)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [groovy中的特殊注解1](https://download.youkuaiyun.com/download/weixin_35798040/86344467)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值