频 道 直 达 - 新闻 - 读书 - 培训 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

使用Java实现内部领域特定语言(4)

作者: Alex Ruiz and Jeff Bay/沙晓兰 编译 出处:InfoQ中文站 2008-03-20 13:48    砖    好    评论   进入论坛
阅读提示:领域特定语言(DSL)通常被定义为一种特别针对某类特殊问题的计算机语言,它不打算解决其领域外的问题。本文将描述怎样使用Java语言来编写领域特定语言,并将建议一些组建DSL语言时可采用的模式。
 
以下是第四个版本,连贯接口更完善的版本。这次,方法返回的是中间对象,而不是this:
 
Period vacation = from("10/09/2007").to("10/17/2007");
Booking booking = vacation.book(city("Paris").hotel("Hilton"));
booking.add(airline("united").flight("UA-6886");

这里,我们引进了Period、Booking、Location、BookableItem(Hotel和Flight)、以及 Airline的概念。在这里的上下文中,airline作为Flight对象的一个工厂;Location是Hotel的工厂,等等。我们所想要的booking的文法隐含了所有这些对象,几乎可以肯定的是,这些对象在系统中会有许多其他重要的行为。采用中间对象,使得我们可以对用户行为可否的限制进行编译器校验。例如,如果一个API的用户试图只通过提供一个开始日期而没有明确结束日期来预定假期的话,代码则不会被编译。正如我们之前提到,我们可以创建一种使用文法来增强语义的语言。
 
我们在上面的例子中还引入了静态工厂方法的应用。静态工厂方法在与静态import同时使用的时候,可以帮助我们创建更简洁的连贯接口。若没有静态import,上面的例子则需要这样的代码:
 
Period vacation = Period.from("10/09/2007").to("10/17/2007");
Booking booking = vacation.book(Location.city("Paris").hotel("Hilton"));
booking.add(Flight.airline("united").flight("UA-6886");
 
上面的例子不及采用了静态import的代码那么易读。在下面的章节中,我们将对静态工厂方法和import做更详细的讲解。
 
这是关于使用Java编写DSL的第二个例子。这次,我们将Java reflection的使用进行简化:
 
Person person = constructor().withParameterTypes(String.class)
.in(Person.class)
.newInstance("Yoda");
method("setName").withParameterTypes(String.class)
.in(person)
.invoke("Luke");
field("name").ofType(String.class)
.in(person)
.set("Anakin");
 
在使用方法链接的时候,我们必须倍加注意。方法链接很容易会被烂用,它会导致许多调用被一起链接在单一行中的“火车残骸”现象。这会引发很多问题,包括可读性的急剧下滑以及异常发生时栈轨迹(stack trace)的含义模糊。
 
2、静态工厂方法和Imports

静态工厂方法和imports可以使得API更加简洁易读。我们发现,静态工厂方法是在Java中模拟命名参数的一个非常方便的方法,是许多程序员希望开发语言中所能够包含的特性。比如,对于这样一段代码,它的目的在于通过模拟一个用户在一个JTable中选择一行来测试GUI:
 

dialog.table("results").selectCell(6, 8); // row 6, column 8

 
没有注释“// row 6, column 8”,这段代码想要实现的目的很容易被误解(或者说根本没有办法理解)。我们则需要花一些额外的时间来检查文档或者阅读更多行代码才能理解“6”和“8”分别代表什么。我们也可以将行和列的下标作为变量来声明,而非像上面这段代码那样使用常量:
 

int row = 6;
int column = 8;
dialog.table("results").selectCell(row, column);

 
我们已经改进了这段代码的可读性,但却付出了增加需要维护的代码的代价。为了将代码尽量简化,理想的解决方案是像这样编写代码:
 
dialog.table("results").selectCell(row: 6, column: 8);
 
不幸的是,我们不能这样做,因为Java不支持命名参数。好的一面的是,我们可以通过使用静态工厂方法和静态imports来模拟他们,从而可以得到这样的代码:
 

dialog.table("results").selectCell(row(6).column(8));

 
我们可以从改变方法的签名(signature)开始,通过包含所有参数的对象来替代所有这些参数。在我们的例子中,我们可以将方法selectCell(int, int)修改为:
 
selectCell(TableCell);
TableCell will contain the values for the row and column indices:
 
TableCell将包含行和列的下标值:
 
public final class TableCell {
public final int row;
public final int column;
public TableCell(int row, int column) {
this.row = row;
this.column = column;
}
}
 
这时,我们只是将问题转移到了别处:TableCell的构造函数仍然需要两个int值。下一步则是将引入一个TableCell的工厂,这个工厂将对初始版本中selectCell的每个参数设置一个对应的方法。另外,为了迫使用户使用工厂,我们需要将TableCell的构建函数修改为private:
 
public final class TableCell {
public static class TableCellBuilder {
private final int row;
public TableCellBuilder(int row) {
this.row = row;
}
public TableCell column(int column) {
return new TableCell(row, column);
}
}
public final int row;
public final int column;
private TableCell(int row, int column) {
this.row = row;
this.column = column;
}
}
 

共6页: 上一页 [1] [2] [3] 4 [5] [6] 下一页
【内容导航】
关于 Java  DSL
专题
运营商封堵非法ADSL共享
Java实用开发全集
Java类的基础教程专题
Java发展动态专题
ADSL2+离我们越来越近
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看70832次)
·UML类图详解 (查看64231次)
·UML统一建模语言 (查看34958次)
·C#技术开发指南 (查看33510次)
·C++是垃圾语言?! (查看31761次)
·Java编程开发手册 (1196个砖)
·Java基础教程 (429个砖)
·C#技术开发指南 (309个砖)
·.NET开发手册 (240个砖)
·PB开发教程 (223个砖)
·Java编程开发手册 (654个好)
·Java基础教程 (574个好)
·.NET开发手册 (271个好)
·PB开发教程 (212个好)
·Delphi开发技术手册 (190个好)
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。