科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道跨越边界: 活动记录和 Java 编程中特定于域的语言

跨越边界: 活动记录和 Java 编程中特定于域的语言

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在这篇文章中,将学习 Ruby 提供的一些漂亮方式,可以集成干净的 DSL,让您大开眼界,用一种新的参考框架来审视 Java 的选项。

作者:baggio785 来源:CSDN 2008年2月29日

关键字: java 活动记录

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共5页)

method_missing 和动态行为

有时,想根据外部情况把方法添加到类。例如,假设想在 Ruby 中表示罗马数字。要把它们与字符串分开,可以用 Roman.III 的形式把数字 3 表示成罗马数字。要为每个可能的罗马数字都向 Roman 添加类方法,是不现实的,而且使用 Ruby 时也不需要这么做。可以利用一个小技巧。

在 Ruby 中,在遗漏了一个方法时,Ruby 就会调用 method_missing 方法。可以覆盖它来提供罗马数字,如清单 8 所示:


清单 8. 覆盖 method_missing 方法


class Roman
 def self.method_missing name, *args
  roman = name.to_s
  if(roman =~ /^[IVXLC]*$/)
   roman.gsub!("IV", "IIII")
   roman.gsub!("IX", "VIIII")
   roman.gsub!("XL", "XXXX")
   roman.gsub!("XC", "LXXXX")
   return(roman.count("I") +
       roman.count("V") * 5 +
       roman.count("X") * 10 +
       roman.count("L") * 50 +
       roman.count("C") * 100)
  else
   super(name, *args)
  end
 end
end

这个代码相当简单,但是确实使用了 Java 程序员不熟悉的一些 Ruby 特性。由于覆盖了 method_missing,所以只要这个类的客户调用一个不存在的方法,Ruby 就会调用这个方法。下面说明细节:

  1. 使用两个参数:
    • name 代表方法名
    • *args 代表遗漏方法的参数
  2. name 是个符号,所以首先用 to_s 把它转换成 String
  3. 用正则表达式进行数字是否罗马数字的合理猜测。

  4. 如果数字是罗马数字,就进行一系列替换,让罗马数字更容易处理。IV 是 4 ,IX 是 9,所以只计算 XVI 的出现,还不能得到它们的值。

  5. 为罗马字母的每次出现分配一个值,分别是:I(1)、V(5)、X(10)、 L(50)或 C(100)。

  6. 如果方法不是罗马数字,就调用超类,超类报告方法遗失。

对于 DSL,这个技术极为强大。活动记录使用这个功能实现动态查找器。活动记录没有为每个列实际地添加查找器,而是使用了 method_missing。使用这个策略,活动记录不仅能匹配一个列,还能匹配列的组合。例如,把 nameemail 列添加到 people 表,可以支持 Person 类的 People.find_by_name_and_email 查找器。像这样的细节使得活动记录的用户体验非常舒服。它们也让活动记录的实现非常简洁而有意义,所以在活动记录做的工作不符合自己的要求时,随时可以实现自己的补丁。

Java 编程中的 DSL 回顾

在使用 Java 语言时,选项就非常有限了。元编程更困难,所以很少能够得到活动记录那样的体验。但是如果真的急需 DSL,还是有些选项的。而且不用总是求助于 XML 或标注。下面是一些常用的方法:

  • 对于需求不太迫切的 DSL,可以使用 Java 类、方法和名称构建对英语友好的词汇,并通过消息调用做需要的事。
  • 对于典型的 Java 用户,可以用 XML 构建自己的语言。XML 难以阅读,但是在某些情况下可能有用,并在 Java 世界中相当普遍。
  • 对于已经要求 XML 的解决方案,可以使用 XML 的派生物来简化。Craig Walls 有一个贴子介绍了如何用 XBean 为 Spring 上下文做这件事(请参阅 参考资料)。
  • 可以使用 XML 的替代表示(例如 Relax NG)来简化 XML(请参阅 参考资料)。
  • 当 Java 代码和 XML 都不够用的时候,可以在 JVM 中嵌入一种语言。最好的方式是通过 BeanShell(请参阅 参考资料)。
  • 对于在 Java 应用程序中需要动态脚本的解决方案,可以利用已经有 BeanShell 集成的更加动态的语言。好的示例有 Jython、JRuby 和 Groovy(请参阅 参考资料)。
  • 可以从头开始构建 DSL。在 Java 语言中这很难做到,但是对于某些应用程序来说还是值得一做。

这些主意,每个都有一系列 developerWorks 文章,所以我在这里对它们就不做太多详细介绍了,但是有一点我要提一下。如果需要在 Java 语言中使用 DSL,需要问自己四个问题:

  • 真的需要 DSL 么?通过 Java 技术的一些更聪明的使用,可能可以做到自己需要的事。
  • XML 或 XML 的派生物足够吗?Java 开发人员对于 XML 经常有点儿太热心了,但是有些派生物可以把事情略微简化。
  • 可以在 Java 语言内部 使用其他语言吗?JRuby 正在越来越好,Groovy 正在就位,Jython 也正在变得更稳定。
  • 从头开始构建 DSL 值得吗?用 Java 语言做这件事很难 —— 需要词法器、解析器和语法器。但是可以做到,可能值得做,具体取决于应用程序。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章