Groovy 学习手册(3)

五. Groovy 的设计模式
设计模式是一种非常好的方式,可以使你的代码变得实用,可读又具有扩展性。跟 Java 相比,在 Groovy 里使用设计模式使代码更加简洁和容易。
1. 策略模式
设想一下,下面有三个不同方法用来计算数字相加的总和:
def totalPricesLessThan10(prices) {
int total = 0
for (int price : prices)
if (price < 10) total += price
total
}
def totalPricesMoreThan10(prices) {
int total = 0
for (int price : prices)
if (price > 10) total += price
total
}
def totalPrices(prices) {
int total = 0
for (int price : prices)
total += price
total
}
上面的代码充满了大量的冗余,每个方法之间只有很少不同的改动。在 Groovy 中,你可以使用闭包作为参数,从而减少三个方法的冗余。
def totalPrices(prices, selector) {
int total = 0
for (int price : prices)
if (selector(price)) total += price
total
}
现在,你就剩下一个方法了,这里的selector是闭包的参数名,如果闭包参数是方法里面最后一个参数,你可以把你的闭包实现放在方法的外面,所以,你可以用下面的代码来实现上面三个方法的功能:
totalPrices(prices) { it < 10 }
totalPrices(prices) { it > 10 }
totalPrices(prices) { true }
这样的代码看起来不仅简洁,而且可读性和扩展性都非常好。
2. 元编程
Groovy里的元编程意味着可以为运行时的类增加方法。这样,你就可以为一些通用类添加一些帮助方法使你的代码更加简洁和可读。
(1) 元类
例如,你在编写javax.servlet.Filter类,你需要获取和设置多个session的属性,你可以这样做:
HttpSession.metaClass.getAt = { key -> delegate.getAttribute(key) }
HttpSession.metaClass.putAt = {
key, value -> delegate.setAttribute(key, value)
}
这里的delegate 是闭包里才存在的对象,在上面的代码中它指的就是HttpSession。
接下来你可以这样:
def session = request.session
session['my_id'] = '123'
def id = session['my_id']
(2) Category
Category 是 Groovy 里元编程技术中的一个。Category 是一个用来给已经存在的类增加功能的类。如果你不想把一个类影响整个应用程序,而只是给部分代码给予特殊对待的话,Category 是非常有用的。
使用 Category 的话,你需要创建静态方法,并且要至少有一个特殊类型的形参(例如,Integer),当这个 Category 被使用时,那这个形参类型的对象也一下子有了除了它本身的方法以外,又增加了先前定义的静态方法。调用该方法的对象作为第一个参数。
例如,Groovy 有一个内置的TimeCategory, 用来操作时间和日期,这允许你添加和减去任意长度的时间。例如,
import groovy.time.TimeCategory
def now = new Date()
println now
use(TimeCategory) {
nextWeekPlusTenHours = now + 1.week + 10.hours - 30.seconds
}
println nextWeekPlusTenHours
这时,TimeCategory 添加了很多方法应用于Integer 类上,例如,一些方法的签名如下所示:
static Duration getDays(Integer self)
static TimeDuration getHours(Integer self)
static TimeDuration getMinutes(Integer self)
static DatumDependentDuration getMonths(Integer self)
static TimeDuration getSeconds(Integer self)
Tip
关于TimeCategory API 供你参考。
3. 不存在的方法
在Groovy中你可以拦截不存在方法(调用的方法不是传统意义上的定义),可以使用methodMissing方法。这是一个非常有用的设计模式,当你想在运行是动态定义方法并且使用一个灵活的方法和签名。你写的methodMissing签名如下:
def methodMissing(String name, args)
参数中的name就是不存在方法的名字,args 可以接收所有传递这个方法的参数值。使用这两个参数,你可以编写想让这个方法拥有的任何功能。
下一步,实现非常高效,你可以拦截,缓存,调用这个方法,例如
def methodMissing(String name, args) {
impl = { /* your code */ }
getMetaClass()."$name" = impl
impl()
}
以上实现了缺失的功能,然后将其添加到当前类的元类中,以便将来的调用直接转到实现的方法而不是不存在的方法。 如果您希望多次调用同一个不存在的方法,这可能很有用。
4. 委托机制
委派是当一个类在方法中直接调用(方法签名是唯一的)另一个类的方法。 这在Java中很难实现,因为向类中添加方法是很困难和耗时的。
在Groovy 2.0中使用新的@Delegate注解会非常容易, 这就像编译期间的元编程。 它会自动将委托类的方法添加到当前类中。例如:
public class Person {
def eatDonuts() { println("yummy") }
}
public class RoboCop {
@Delegate final Person person
public RoboCop(Person person) { this.person = person }
public RoboCop() { this.person = new Person() }
def crushCars() {
println("smash")
}
}
尽管RoboCop 没有eatDonuts方法,但是所有Person类的方法都添加给了RoboCop类,并且委派了person变量,下面的使用是没有问题的:
def person = new RoboCop()
person.eatDonuts()
person.crushCars()
Groovy 学习手册(3)的更多相关文章
- Groovy 学习手册(7)
10. Groovy GPars GPars 一开始在 Groovy 中作为一个单独的项目,同时带来了很多并发的机制.它包含了很多并行的map/redue,Actors,以及其他很多并发的模块. 1. ...
- Groovy 学习手册(6)
9. 不可变特性 不可变特性和函数式编程在一起就像是花生酱和果酱在一起一样.虽然没有必要非要在一起使用,但他们相处得很好. 在纯正的函数式语言中,每个函数对本身之外没有影响,即没有副作用.这意味着每次 ...
- Groovy 学习手册(5)
8. 函数式编程 函数式编程(FP)是一种编程风格,侧重于函数和最小化状态的变化(使用不可变的数据结构).它更接近于用数学来表达解决方案,而不是循序渐进的操作. 在函数式编程里,其功能应该是" ...
- Groovy 学习手册(4)
6. 领域特定语言 Groovy 有许多特性,使它非常适合写DSL(领域特定语言).这些特性包活: 具有委托机制的闭包: 点号(.)和语句末尾的分号(;)是可选的: 运算符的重载(例如,加号,减号等) ...
- Groovy 学习手册(2)
二. 工具 1. 控制台 groovyConsole: Groovy 控制台是一个非常易于使用和简单的轻量级的编辑器.你可以在里面做很多事情. 在编辑器里面可以书写代码,Windows 下,按下Ctr ...
- Groovy 学习手册(1)
1. 需要安装的软件 Java / Groovy 对应 Java 和 Groovy,你需要安装以下软件: Java JDK,例如 JDK 8 IDE,例如 Eclipse,NetBeans 8 Gro ...
- Kotlin强化实战!这份学习手册让你的面试稳如泰山
一.引言 正如官网的slogan所描述:kotlin,是一门让程序员写代码时更有幸福的现代语言. 同时,也正如维基百科里介绍: JetBrains公司希望Kotlin能够推动IntelliJ IDEA ...
- Redis学习手册(目录)
为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...
- git学习手册
#git学习手册 git: Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.[2] Git 是 Linus Torvalds 为了帮助管理 Linux内核开发而 ...
随机推荐
- 【高德地图Android SDK】视频教学
前两天参加了高德在北航举办的公开课,感觉非常不错.完成老师布置的作业之后,还顺利地拿到了高德开发者认证证书!! 现在来跟大家分享一下,如何快速学习[高德地图Android SDK]的开发.一天包会!连 ...
- ngx_lua实现页面跳转
好久不用ngx_lua了,忽然被问到如何实现页面跳转,半天没反应过来,查了半天资料搞出来的,在这里做一个备份. 需求说明:***.taobao.com 跳转到 www.taobao.com/?url= ...
- Nginx 与Tomcat 实现动静态分离、负载均衡
Nginx 与Tomcat 实现动静态分离.负载均衡 一.Nginx简介: Nginx一个高性能的HTTP和反向代理服务器, 具有很高的稳定性和支持热部署.模块扩展也很容易.当遇到访问的峰值,或者有人 ...
- 解决 Out of range value adjusted for column 'ID' at row 1
MySQL升级到5.0.17后,在执行sql语句INSERT INTO `news` (`ID`, `Title`, `Content`) VALUES ('', '标题', '正文');时出现错误: ...
- iOS UI01_Label
@implementation AppDelegate -(void)dealloc { [_window release]; [superdealloc]; } - (BOOL)applicatio ...
- Xamarin.Android其他类型的服务
一.前言 前面我们已经学了关于服务的很多知识,但是对于真实的开发那些远远不够,通过这节我们将学习其他类型的服务,比如前台服务.IntentService和消息服务.下面我们开始进入正题. 二.前台服务 ...
- 7、redis之使用spring集成commons-pool来操作常见数据类型
环境的搭建参见:http://www.cnblogs.com/yangzhilong/p/4729857.html 下面直接贴具体的测试代码: package com.yzl; import java ...
- 怎么解决numpy和matplotlib无法安装问题
使用python setup.py install 折腾了半天没办法解决,最终用 “pip install 包名” 这个办法解决了. 以后忠诚的爱上了pip了 numpy不要轻易升级,升级可能会 ...
- shell笔记-算术运算
算术运算在Bash shell环境中,可以利用let.(( ))和[]执行基本的算术操作.而在进行高级操作时,expr和bc这两个工具也会非常有用.let命令可以直接执行基本的算术操作.当使用let时 ...
- android webview goback 跳过页面302自动跳转方法
转自http://blog.csdn.net/dyllove98/article/details/8827529 http://hi.baidu.com/519177819/item/3a340f16 ...