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内核开发而 ...
随机推荐
- 【树莓派】Squid代理以及白名单配置
Squid安装: sudo apt-get install squid3 -y 首先,建议备份一下这个配置文件,以免配错之后,无法恢复,又得重新安装: sudo cp /etc/squid3/squi ...
- 利用 pywin32 操作 excel
from win32com.client import Dispatch import win32com.client import time # 获取excel 对象 excel = win32co ...
- Java并发容器之CopyOnWriteArraySet与ConcurrentSkipListSet
一:CopyOnWriteArraySet CopyOnWriteArraySet底层其实是通过CopyOnWriteArrayList来实现的,通过组合一个CopyOnWriteArrayList作 ...
- 在vim中安装及配置NERDTree插件
使用Vundle插件安装,在.vimrc中加入以下代码: Plugin 'scrooloose/nerdtree' 打开vim,输入命令如下: :BundleInstall 等待安装完毕 配置NERD ...
- Linux下pppoe设置
在Linux下配置pppoe,一般有以下步骤: 1. 安装pppoe软件.这个不多说,ape-get install pppoe即可. 2. 设置拨号属性: [cpp] view plain copy ...
- spiral-matrix-ii &i 生成顺时针序列
I: Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral ...
- 如何区分一个android app是h5的还是native
关闭网络连接 请求一个新的界面,如果是原生的 请求失败最起码有一些基本的ui,如果h5就最多有个标题. 在wifi 设置代理,这样h5就不能正常的访问网址了会出现404 ,原生的有基本ui
- Jenkins+Ant+Jmeter搭建持续集成的接口测试平台(转)
一.什么是接口测试? 接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点.测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻 ...
- Arduino和C51开发光敏传感器
技术:51单片机.Arduino.光敏传感器.PCF8591.AD/DA转换 概述 本文介绍了如何接收传感器的模拟信号和如何使用PCF8591 AD/DA转换模块对光敏传感器的模拟信号进行转换.讲 ...
- JS正则替换掉小括号及内容
正則表達式:\ ( [ ^ \ ) ] * \ ) JS代码: var str="hello(world)"; var nstr = str.replace(/\([^\)]*\) ...