现在的位置: 首页 > 综合 > 正文

Groovy探索 DSL在Calendar类上的实践 一

2013年12月10日 ⁄ 综合 ⁄ 共 4160字 ⁄ 字号 评论关闭

                  Groovy探索 DSL在Calendar类上的实践 一

 

 

作为一个使用者,我不喜欢Java平台的Calendar类;同样,我也不喜欢Groovy平台的Calendar类。都是基于同样的原因,使用起来非常不方便。

同时,Groovy语言的DSL极大的吸引了我。使得我每每在使用Calendar类的时候,都会想到我可否使用DSL来改造这个Calendar类呢,权当一次使用DSL的实验。

在这样的想法下,我写了一点的DSL代码,用来检验我对于DSL的理解,同时,也想抛砖引玉,引来大家对于使用DSL来改造Calendar类的一些想法。

首先,我不喜欢使用如下的代码来获取单独的年、月、日的数据:

 

       Calendar c = Calendar.getInstance();

      

       System.out.println(c.get(Calendar.YEAR));

 

我喜欢形如"c.year"这样的代码来获取单独的年、月、日的数据。这种想法很简单,实现起来也不难,不就是给Calendar类多加几个"get"方法嘛。

我构造起我自己的Calendar类来,如下所示:

 

class MyCalendar {

   

    def cal

   

    def type

   

    def MyCalendar()

    {

       cal = Calendar.instance

    }

   

    def getDate()

    {

       cal.get(Calendar.DATE)

    }

   

    def getMonth()

    {

       cal.get(Calendar.MONTH)+1

    }

   

    def getYear()

    {

       cal.get(Calendar.YEAR)

    }

   

}

 

 

一切都很简单,现在,我们来测试一下吧:

 

      def c = new MyCalendar()

     

      println c.year+'/'+c.month+'/'+c.date

 

 

运行结果为:

2009/3/16

 

真的还蛮顺利的。

接着,我也不喜欢Calendar类的"set"方法,它的形式是这样的:

 

       c.set(Calendar.YEAR, 2010);

   

如果我既想设定年份,还想设定月份,那么必须这么写:

 

       c.set(Calendar.YEAR, 2010);

      

       c.set(Calendar.MONTH, 3);

   

 

我喜欢这样的形式:

 

      c.set(year:2010)

 

 

这也很简单啊,不就是一个Map参数的方法嘛,于是,我在MyCalendar类里继续加入了如下的方法:

   

    def set(map)

    {

       if(map.year)

       {

           cal.set(Calendar.YEAR,map.year)

       }

       if(map.month)

       {

           cal.set(Calendar.MONTH,map.month)

       }

       if(map.date)

       {

           cal.set(Calendar.DATE,map.date)

       }

    }

 

 

现在,我们就可以写代码来测试一下了:

 

      def c = new MyCalendar()

     

      c.set(year:2010)

     

      println c.year+'/'+c.month+'/'+c.date

 

运行的结果为:

2010/3/16

 

当然了,如果我们既想设定年份,又想设定月份,代码就是形如下面的形式:

 

      c.set(year:2010,month:4)

 

 

对于年份的运算,比如当前年份加上3年,我就更不喜欢下面的形式了:

Calendar c = Calendar.getInstance();

      

       c.set(Calendar.YEAR, c.get(Calendar.YEAR)+3);

      

    System.out.println(c.get(Calendar.YEAR));

 

我喜欢下面的形式:

 

      c = c+3.year

 

要达到上述的目的,我们首先要在MyCalendar类里重载"plus"方法,使得MyCalendar类能够和数字相加。

   

    def plus(howlong)

    {

       if(type==1)

       {

           cal.set(Calendar.YEAR,getYear()+howlong)

       }

       else if(type==2)

       {

           cal.set(Calendar.MONTH,getMonth()+howlong)

       }

       else if(type==3)

       {

           cal.set(Calendar.DATE,getDate()+howlong)

       }

       this

}

 

首先判定相加的数字是年份、月份还是日期,然后再使用Calendar类的加法。

接着,光重载"plus"方法还不够,我们需要识别形如"3.year"这样的表达式。在这里,Groovy语言的MOP能帮得上忙。

 

      def mc = new ExpandoMetaClass(Integer.class,true)

     

      mc.getDate <<

      {

         ->

        

           c.type = 3

        

           delegate

      }

     

      mc.getMonth <<

      {

         ->

           c.type = 2

           delegate

      }

     

      mc.getYear <<

      {

         ->

        

           c.type = 3

        

           delegate

      }

     

  mc.initialize()

 

当所有这一切完成之后,我们就可以来测试了:

 

      c = c+3.date

     

      println c.year+'/'+c.month+'/'+c.date 

     

      c = c+2.month

     

  println c.year+'/'+c.month+'/'+c.date

 

运行结果为:

 

2010/5/19

2010/8/19

 

最后,我把整个的Calendar类的代码附上。

class MyCalendar {

   

    def cal

   

    def type

   

    def MyCalendar()

    {

       cal = Calendar.instance

    }

   

    def getDate()

    {

       cal.get(Calendar.DATE)

    }

   

    def getMonth()

    {

       cal.get(Calendar.MONTH)+1

    }

   

    def getYear()

    {

       cal.get(Calendar.YEAR)

    }

   

    def plus(howlong)

    {

       if(type==1)

       {

           cal.set(Calendar.YEAR,getYear()+howlong)

       }

       else if(type==2)

       {

           cal.set(Calendar.MONTH,getMonth()+howlong)

       }

       else if(type==3)

       {

           cal.set(Calendar.DATE,getDate()+howlong)

       }

       this

    }

   

    def set(map)

    {

       if(map.year)

       {

           cal.set(Calendar.YEAR,map.year)

       }

       if(map.month)

       {

           cal.set(Calendar.MONTH,map.month)

       }

       if(map.date)

       {

           cal.set(Calendar.DATE,map.date)

       }

    }

 

  static void main(args) {

     

      def c = new MyCalendar()

     

      println c.year+'/'+c.month+'/'+c.date

     

      c.set(year:2010,month:4)

     

      println c.year+'/'+c.month+'/'+c.date

     

     

      def mc = new ExpandoMetaClass(Integer.class,true)

     

      mc.getDate <<

      {

         ->

        

           c.type = 3

        

           delegate

      }

     

      mc.getMonth <<

      {

         ->

           c.type = 2

           delegate

      }

     

      mc.getYear <<

      {

         ->

        

           c.type = 3

        

           delegate

      }

     

      mc.initialize()

     

      c = c+3.date

     

      println c.year+'/'+c.month+'/'+c.date 

     

      c = c+2.month

     

      println c.year+'/'+c.month+'/'+c.date

 

  }

 

}

抱歉!评论已关闭.