• Groovy 与 DSL


    一:DSL 概念

    指的是用于一个特定领域的语言(功能领域、业务领域)。在这个给出的概念中有 3个重点:

    只用于一个特定领域,而非所有通用领域,比如 Java / C++就是用于通用领域,而不可被称为 DSL,同样也不可把 Groovy称为 DSL。

    语言,必须经过编写后才可发挥它的功能。比如:五线谱编写后成乐谱; ANT编写用于编译; SVN命令编写后可对资源库进行操作; Shell编程; SQL编程; PL-SQL编程等等。

    忽略具体的运行环境(媒介),可以是纸、 XML文件、命令行、 Shell、数据库等。

    二:Groovy对 DSL的支持

    Groovy不是 DSL,而是通用的编程语言。但 Groovy却对编写出一个全新的 DSL提供了良好的支持,这些支持都来自于 Groovy自身语法的特性,比如:

    不需要 class定义,直接执行脚本

    Groovy语法的简洁

    Groovy提供了更多通俗易懂的方法

    省略()和;等

    等等

    Groovy自身不是 DSL。 Groovy官方已经发布了较多基于 Groovy书写的 DSL,比如 GANT, GORM, XMLBuilder, HtmlBuilder等等。

    三:我们的目标

    实现一种使用 Groovy语法书写、用于构建 HTML的(其实就是 HtmlBuilder)的简单 DSL,如下:

    html {  
        head {  
            meta {  
                  
            }  
        }  
        body {  
            table (style:'margin:5px;') {  
                tr ('class':'trClass', style:'padding:5px;') {  
                    td {'Cell1'}  
                    td {'Cell2'}  
                    td {'Cell3'}  
                }  
            }  
        }  
    }

    这段代码比较容易让人懂,很容易让人将 HTML与之对应起来。具体怎么实现能够通过这一段 DSL代码输出原始的 HTML呢?主要基于 Groovy的以下几个特性:

    Groovy脚本,不用定义 class

    Groovy的 invokeMethod方法

    方法可不书写()

    语句末尾省略;分号

    不书写 return

    四:代码分析

    meta {  
    }  
    //这段代码的含义为:调用 meta方法,参数为一个闭包,闭包不执行任何代码。
    
    table (style:'margin:5px;') {  
    }  
    //这段代码的含义为:调用 table方法,第一个参数为 Map,第二个参数为闭包。
    
    tr ('class':'trClass', style:'padding:5px;') {  
                    td {'Cell1'}  
                    td {'Cell2'}  
                    td {'Cell3'}  
    }  
    //这段代码的含义为:
    //调用 tr方法,第一个参数为 Map,第二个参数为闭包。
    //闭包中,调用了 3 个 td方法,参数都为一个闭包;闭包中直接返回了一个字符串。

    五:代码实现

    将代码解读了以后,再结合 invokeMethod就很容易实现了,具体代码如下:

    def invokeMethod(String name, args) {  
        print "<${name}"  
        args.each { arg ->  
            if (arg instanceof Map) {  
                arg.each {  
                    print " ${it.key} ='${it.value}' "  
                }  
            } else if (arg instanceof Closure) {  
                print '>'  
                arg.delegate = this  
                def value = arg.call()  
                if (value) {  
                    print "${value}"  
                }  
            }  
        }  
      
        println "</${name}>"  
    }  
      
    html {  
        head {  
            meta {  
                  
            }  
        }  
        body {  
            table (style:'margin:5px;') {  
                tr ('class':'trClass', style:'padding:5px;') {  
                    td {'Cell1'}  
                    td {'Cell2'}  
                    td {'Cell3'}  
                }  
            }  
        }  
    }

    六:运行结果

    <html><head><meta></meta>  
    </head>  
    <body><table style ='margin:5px;' >
    <tr class ='trClass' style ='padding:5px;' >
    <td>Cell1</td>  
    <td>Cell2</td>  
    <td>Cell3</td>  
    </tr>  
    </table>  
    </body>  
    </html>

    七:结论基于Groovy自身的语法简洁和众多特性,实现一个专属的DSL还是蛮简单的。

  • 相关阅读:
    android_handler(二)
    android_handler(一)
    java_synchronized 用法
    android surfaView surfaHolder video 播放
    《Java 8 实战》读书笔记
    Java面试宝典——基础部分
    Shell脚本---处理用户输入
    《Spring》(十八)---- 事务管理
    《Spring》(十七)---- JDBC访问数据
    《Spring》(十六)---- 基于Schema的AOP
  • 原文地址:https://www.cnblogs.com/xingzc/p/6347673.html
Copyright © 2020-2023  润新知