Groovy:程序员的 DSL

2024-06-24 07:48
文章标签 程序员 groovy dsl

本文主要是介绍Groovy:程序员的 DSL,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是DSL?

领域特定语言,针对一个特定的领域,具有受限表达性的一种计算机程序语言。可以看做是一种抽象处理的方式。

具有四个元素,第一个是计算机程序设计语言,使用DSL来指挥计算机做事情,语言性(一种特定的语言),受限的表达性,并不像同通用的设计语言那样具有广泛的能力,针对一个明确的领域。

分类有哪些?

外部DSL:不同于应用系统主要使用语言的语言,通常采用自定义语法,宿主应用的代码采用文本解析技术对外部DSL编写的脚本进行解析。例子如:正则表达式、SQL、AWK以及Struts的配置文件等

内部DSL:通用语言的特定语法,用内部DSL写成的脚本是一段合法的程序,但是它具有特定的风格,而且仅仅用到了语言的一部分特性,用于处理整个系统一个小方面的问题;

语言工作台:一种专用的IDE,用于定义和构建DSL,具体的讲,语言工作台不仅用来确定DSL的语言结构,而且是人们编写DSL脚本的编辑环境,最终的脚本讲编辑环境和语言本身紧密的结合在一起;

为什么需要DSL?

1、提高开发效率,通过DSL来抽象构建模型,抽取公共的代码,减少重复的劳动;

2、和领域专家沟通,领域专家可以通过DSL来构建系统的功能;

3、执行环境的改变,可以弥补宿主语言的局限性;

DSL的处理可能包含那几个步骤?

1、DSL脚本;

2、解析脚本;

3、语义模型;

4、生成代码或者执行模型;

为啥groovy能比较好的构建DSL?

1、不需要class文件,可以直接执行脚本;

2、闭包等特性以及语法的简介,使用非常灵活;

3、可以和java系统无缝的整合;

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

使用groovy做DSL的例子?

1、一个自定义的dsl,例如这个:

ParseDsl.make {to "Nirav Assar"from "Barack Obama"body "How are things? We are doing well. Take care"idea "The economy is key"request "Please vote for me"xml}

2、那必须要有地方解析这个规则:

//groovy methodMissing如果找不到方法,就会调用这个方法 里面用到了这个特性

import groovy.xml.MarkupBuilder;
/**
* 解析一个自定义的DSL文本的类,类似解析规则
*/
class ParseDsl {String toTextString fromTextString bodydef sections = []def static make(closure) {ParseDsl memoDsl = new ParseDsl()closure.delegate = memoDslclosure()}def to(String toText) {this.toText = toText}def from(String fromText) {this.fromText = fromText}def body(String bodyText) {this.body = bodyText}def methodMissing(String methodName, args) {def section = new Section(title: methodName, body: args[0])sections << section}def getXml() {doXml(this)}def getHtml() {doHtml(this)}def getText() {doText(this)}private static doXml(ParseDsl memoDsl) {def writer = new StringWriter()def xml = new MarkupBuilder(writer)xml.memo() {to(memoDsl.toText)from(memoDsl.fromText)body(memoDsl.body)for (s in memoDsl.sections) {"$s.title"(s.body)}}println writer}private static doHtml(ParseDsl memoDsl) {def writer = new StringWriter()def xml = new MarkupBuilder(writer)xml.html() {head {title("Memo")}body {h1("Memo")h3("To: ${memoDsl.toText}")h3("From: ${memoDsl.fromText}")p(memoDsl.body)for (s in memoDsl.sections) {p {b(s.title.toUpperCase())}p(s.body)}}}println writer}private static doText(ParseDsl memoDsl) {String template = "Memo\nTo: ${memoDsl.toText}\nFrom: ${memoDsl.fromText}\n${memoDsl.body}\n"def sectionStrings =""for (s in memoDsl.sections) {sectionStrings += s.title.toUpperCase() + "\n" + s.body + "\n"}template += sectionStringsprintln template}
}

关于groovy中的闭包?

http://docs.codehaus.org/pages/viewpage.action?pageId=167477326

groovy中的闭包是一个匿名的代码块,可以接受参数,并返回一个返回值,也可以引用和使用在他周围的,可见域中定义的变量。Groovy 之所以包含闭包,是因为它可以让开发者写出更简约、更易懂的代码。Java 开发者通常用一个单方法的接口(Runable,采用Command设计模式),并结合匿名内部类来实现;而Groovy 则允许以一种更简易、直白的方式来实现。额外的,相较匿名内部类,闭包有很少量的约束,包括一些额外的功能。

例子代码:

//第一个例子
def shout = {src->return src.toUpperCase()}println shout("Hello World")//模拟一个for循环的例子,在List的循环中添加Closuredef names = ["alibaba-inc.com","bixiao.zy","hello world","iamzhongyong"]printInfo = {println "hello,${it},welcome"}names.each printInfo//Colsure作为方法的入参def closureMethod(Closure c) {c.call("iamzhongyong")
}
closureMethod { name->println "Closure called "+name
}//为参数提供默认值
greetString = { greet,name = "iamzhongyong" ->return "${greet},${name}"
}
assert greetString("welcome") == "welcome,iamzhongyong"
assert greetString("hello","bixiao.zy") == "hello,bixiao.zy"//使用闭包实现单方法接口
interface Test {def one()
}
def test = {println 'one'} as Test
test.one()//使用闭包实现多方法接口
interface Test {def one()def two()
}
def test = [one: {println 'one'},two: {println 'two'}] as Test
test.one()
test.two()

lambda和闭包(closure)的区别是什么

lambda就是匿名函数——即没有名字的函数。前面你已经看到过一些例子了。闭包就是封闭在其定义所处环境的任意函数。

 

http://lggege.iteye.com/blog/543730

http://docs.codehaus.org/pages/viewpage.action?pageId=167477326

http://groovy.codehaus.org/Builders

http://confluence.jetbrains.com/display/GRVY/Scripting+IDE+for+DSL+awareness

http://java.dzone.com/articles/groovy-dsl-simple-example

这篇关于Groovy:程序员的 DSL的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089547

相关文章

ElasticSearch的DSL查询⑤(ES数据聚合、DSL语法数据聚合、RestClient数据聚合)

目录 一、数据聚合 1.1 DSL实现聚合 1.1.1 Bucket聚合  1.1.2 带条件聚合 1.1.3 Metric聚合 1.1.4 总结 2.1 RestClient实现聚合 2.1.1 Bucket聚合 2.1.2 带条件聚合 2.2.3 Metric聚合 一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

LabVIEW程序员是怎样成长为大佬

成为一名LabVIEW编程领域的“大佬”需要时间、实践、学习和解决复杂问题的经验。尽管LabVIEW作为一种图形化编程语言在初期可能相对容易上手,但要真正成为精通者,需要在多个层面上深入理解。以下是LabVIEW程序员如何逐步成长为“大佬”的路径: 1. 打好基础 LabVIEW的大佬们通常在初期会打下非常坚实的基础,理解LabVIEW编程的核心概念,包括: 数据流编程模型:Lab

程序员必备心理学——心流

心理学之心流 前言一、“心流”是什么?二、心流的好处二、如何进入心流心流状态的四个阶段第一个阶段:挣扎第二个阶段:放松第三个阶段:心流第四个阶段:巩固 进入心流的技巧 总结题外话 前言 你是否常常感觉自己明明学习了一整天,但是就是感觉没有太多的收获。这个时候除了你的学习方向等问题之外,也可能是你的学习方法太低效了。作者本人就经常有这种情况,好在偶然间在b站刷到一个大佬的这个心

ElasticSearch的DSL查询④(DSL查询、RestClient的DSL查询)

目录 一、DSL查询 1.1 快熟入门 1.2 叶子查询 1.2.1 全文检索查询 1)match查询 2)multi_match查询 1.2.2 精确查询 1)term查询 2)range查询 3)ids查询 1.3 复合查询 1.3.1 bool查询 1.3.2 算分函数查询 1)基本语法: 2)运行流程: 3)示例: 4)执行结果: 1.4 排序 1.5

程序员都在使用的画图工具

大家好,我是袁庭新。 程序员都在使用的画图工具,你一定没用过这款画图工具吧!我教程中的架构图都是用它来画的。 比如我编写的RDB工作原理图就是用draw.io绘制的,如下图所示: 再例如Redis集群故障恢复原理图我也是通过draw.io工具绘制的,如下图所示: 是不是觉得draw.io绘制的图形特别简洁、美观。它的官网是: https://www.drawio.com dra

GitHub:代码是程序员沟通最直接的手段

如果不是 Andreessen horowitz 的投资,估计 GitHub 很难被福布斯、CNN、纽约时报等传统媒体注意到。普通大众之前不了解这个工具,是因为它距离记者的世界太远了——GitHub 是一个程序员所使用的托管项目的服务。 但在一些程序员眼里,它不仅是托管项目的地方,还是“开源”项目的大本营,而且是提高程序员“技术水平”和“技术品味”的地方,更是一个程序员社交的地方。

黑马程序员---银行业务调度系统

模拟实现银行业务调度系统逻辑 需求分析: 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。 异步随机生成各种类型的客户,生成各类型用户的概率比例为:         VIP客户 :普通客户 :快速客户 =  1:6:3。 客户办理业务所

黑马程序员---空中网面试题

空中网4k/5k月薪挑选大四实习生的线程题     两年前,我们一个大四的学员去应聘空中网的实习生职位,空中网只给他出了三道线程题,拿回家做两天后再去给经理讲解,如果前两题做好了给4k月薪,第三道题也做出来的话就给5k的月薪。这样的实习薪水和招聘要求,不需要有工作经验的限制,纯粹是技术功底的比拼和考核,而不像许多其他公司非要招两年工作经验的人,逼得那些刚毕业和未毕业的大学生不得不去撒谎,不得不去做

黑马程序员---线程并发库

软件包 java.util.concurrent 在并发编程中很常用的实用工具类。 请参见:            描述 接口摘要BlockingDeque<E>支持两个附加操作的 Queue,这两个操作是:获取元素时等待双端队列变为非空;存储元素时等待双端队列中的空间变得可用。BlockingQueue<E>支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及

黑马程序员---多线程

TraditionalTread 传统线程技术回顾 创建线程的两种方式: thread3中,同时创建了Thread的子类和Runnable,那么会优先执行Thread的子类,因为Runnable的代码被当做参数传到了Thread类里,Thread子类的run方法又覆盖了父类的方法,所以会执行Thread子类的代码。 package cn.itcast.heima;public class T