五. 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)的更多相关文章

  1. Groovy 学习手册(7)

    10. Groovy GPars GPars 一开始在 Groovy 中作为一个单独的项目,同时带来了很多并发的机制.它包含了很多并行的map/redue,Actors,以及其他很多并发的模块. 1. ...

  2. Groovy 学习手册(6)

    9. 不可变特性 不可变特性和函数式编程在一起就像是花生酱和果酱在一起一样.虽然没有必要非要在一起使用,但他们相处得很好. 在纯正的函数式语言中,每个函数对本身之外没有影响,即没有副作用.这意味着每次 ...

  3. Groovy 学习手册(5)

    8. 函数式编程 函数式编程(FP)是一种编程风格,侧重于函数和最小化状态的变化(使用不可变的数据结构).它更接近于用数学来表达解决方案,而不是循序渐进的操作. 在函数式编程里,其功能应该是" ...

  4. Groovy 学习手册(4)

    6. 领域特定语言 Groovy 有许多特性,使它非常适合写DSL(领域特定语言).这些特性包活: 具有委托机制的闭包: 点号(.)和语句末尾的分号(;)是可选的: 运算符的重载(例如,加号,减号等) ...

  5. Groovy 学习手册(2)

    二. 工具 1. 控制台 groovyConsole: Groovy 控制台是一个非常易于使用和简单的轻量级的编辑器.你可以在里面做很多事情. 在编辑器里面可以书写代码,Windows 下,按下Ctr ...

  6. Groovy 学习手册(1)

    1. 需要安装的软件 Java / Groovy 对应 Java 和 Groovy,你需要安装以下软件: Java JDK,例如 JDK 8 IDE,例如 Eclipse,NetBeans 8 Gro ...

  7. Kotlin强化实战!这份学习手册让你的面试稳如泰山

    一.引言 正如官网的slogan所描述:kotlin,是一门让程序员写代码时更有幸福的现代语言. 同时,也正如维基百科里介绍: JetBrains公司希望Kotlin能够推动IntelliJ IDEA ...

  8. Redis学习手册(目录)

    为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...

  9. git学习手册

    #git学习手册 git: Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.[2] Git 是 Linus Torvalds 为了帮助管理 Linux内核开发而 ...

随机推荐

  1. crm创建启用停用用户

    public static readonly string entityName = "systemuser";         public Guid userId = Guid ...

  2. iOS开发技巧 - 使用Alerts和Action Sheets显示弹出框

    解决方案: (Swift) 使用UIAlertController类 (Objective-C) 使用UIAlertView类 代码: (Swift) import UIKit class ViewC ...

  3. Android Developers:按钮

    按钮是有文本或者图标(或者文本和图标)组成,它传达用户触摸它的时候所发生的动作. 你可以在你的布局中使用三种方式创建按钮,取决于你是否想创建文本按钮,突变按钮或者两者都有: 设置文本,使用Button ...

  4. Linux中禁用THP(Transparent Huge Pages)

    一.简介 Centos6开始引入THP,Centos7时默认启用,用来提升内存性能. 二.说明 争对一些数据库,如Oracle.MariaDB.MongoDB.VoltDB在使用时,要求关闭此功能. ...

  5. 014-Go Web 对pg增删改查测试

    1:data/data.go package data import( "fmt" "database/sql" _"github.com/lib/p ...

  6. Nginx 访问日志分析

    0:Nginx日志格式配置 # vim nginx.conf ## # Logging Settings ## log_format access '$remote_addr - $remote_us ...

  7. django之创建第4-2个项目-访问class类属性和类方法

    1.修改index <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  8. Easyui入门视频教程 第07集---Accordion的使用

    Accordion 是一个 收缩的组件 类似挂历的 百度了一下 意思是 accordion 英[əˈkɔ:diən] 美[əˈkɔrdiən] n. 手风琴 adj. 可折叠的 他就是 一个折叠的 很 ...

  9. SpringMVC框架学习

    2012-03-21 衡量一个MVC框架模式,主要通过三种web模式,本人认为springMVC是一个很好的MVC 模式,对模式的支持如下: (1)派遣器模式 Spring有一个统一集中的派遣器org ...

  10. usr/bin/X11各个程序中文详解

    X11程序 animate 输出图形结果 bitmap bmtoa bounce 输出X屏幕保存结果 display 浏览编辑image magick图像 editres 编辑X11资源 flsfon ...