我们平时操作时间都用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方法:
其实我们阅读源码的时候,不止要看它是怎么实现的,因为这样你才是看源码的第一层境界,知道源码,掌握源码背后的设计思路,才是说明你看懂了源码。
- 适配器模式获取CalendarProvider
上图中1处,是通过适配器模式获取CalendarProvider创建Calendar。 - 工厂模式获取子类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。