Calendar的内部实现

时间:2022-12-21 11:59:45


我们平时操作时间都用common包中的DateUtils类,可以对时间增加天数,月份,小时,分钟等,你知道么,其实DateUtils只是一个工具类,它的内部是通过Calendar类来进行操作的。

例如,如下代码,我们获取一个当前时间增加两天的时间:

DateUtils.addDays(new Date(), 2);

它的内部是这么实现的:

public static Date add(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(calendarField, amount);
return c.getTime();
}
  • calendarField:增加的时间的单位,天,年,月等
  • amout:增加的数值

那么今天就带你走入Calendar类,看看它是怎么操作的.

一、Calendar抽象类

Calendar是操作时间的抽象类,作为一个抽象类,它却可以自己通过getInstance()方法获取实例,为什么抽象类可以实例化对象,getInstance()方法是怎么实现的呢?

二、getInstance()方法

getinstance()方法里面其实是调用了createCalendar方法:

Calendar的内部实现


其实我们阅读源码的时候,不止要看它是怎么实现的,因为这样你才是看源码的第一层境界,知道源码,掌握源码背后的设计思路,才是说明你看懂了源码。

  1. 适配器模式获取CalendarProvider
    上图中1处,是通过适配器模式获取CalendarProvider创建Calendar。
  2. 工厂模式获取子类Calendar
    上图中2处,是通过工厂模式,获取不同的子类Calendar。

正常情况下,是走到代码1处,获取当前时区的时间。

三、建造者模式获取Calendar

上面获取到CalendarProvider后,是进入了如下代码:

public Calendar getInstance(TimeZone var1, Locale var2) {
return (new Builder()).setLocale(var2).setTimeZone(var1).setInstant(System.currentTimeMillis()).build();
}

如果你了解设计模式的话,会知道,这是一个建造者模式,什么是建造者模式?

  • 建造者模式:一言以蔽之,就是根据不同的参数,创建不同特征的相同实例。

最后是返回了一个Calendar的子类GregorianCalendar。

四、总结

抽象类Calendar可以通过getInstance()方法,获取到实例的实例是子类GregorianCalendar。其中使用了如下设计模式:

  • 适配器模式:获取合适的CalendarProvider
  • 工厂模式:这一步走不到(获取不到CalendarProvider才会走到这里),获取个性化的Calendar
  • 建造者模式:获取自己定义特征的Calendar。