在java 8下更好地利用枚举-亚博电竞手机版

在我们的云使用分析api中,返回了格式化过的分析数据(这里指生成分析图)。最近,我们添加了一个特性,允许用户选择时间段(最开始只可以按天选择)。问题是,代码中每天中的时间段部分高度耦合了……

例如,下面这段代码:

private static list createlistwithzerosfortimeinterval(datetime from, 	datetime to, 	immutableset> metrics) { 	list points = new arraylist<>(); 	for (int i = 0; i <= days.daysbetween(from, to).getdays(); i  ) { 		points.add(new datapoint().withdatas(createdataswithzerovalues(metrics)) 			.withdayofyear(from.withzone(datetimezone.utc) 				.plusdays(i) 				.withtimeatstartofday())); 	} 	return points; }

注意:days、minutes、hours、weeks 和months一样出现在代码的后面部分。这些代码来自joda-time java时间和日期api。甚至方法的名字都没有反应出(各自的功能)。这些名字牢牢的绑定到了days的概念上。

我也尝试过使用不同时间段方式(比如月、周、小时)。但我看到了糟糕的switch/case鬼鬼祟祟地隐藏在代码里。

你需要知道,switch/case=罪恶 已经深入我心了。在我大学期间的两段实习经历中就已经这么认为了。因此,我会不惜任何代价避免使用switch/case。这主要是因为它们违反了开放闭合原则。我深深地相信,遵循这个原则是写出面向对象代码的最好实践。我不是唯一一个这样想的,robert c. martin曾经说:

在很多方面,开放闭合原则是面向对象设计的核心。遵循这个原则会从面向对象技术中收获巨大的好处,比如可重用性和可维护性1

我告诉自己:“我们使用java8或许可以发现一些新的特性来避免swtich/case的危险场面出现”。使用java8的新 functions(不是那么新,不过你知道我的意思)。我决定使用枚举代表不同的可得到时间段。

public enum timeperiod {     minute(dimension.minute,             (from,             to) -> minutes.minutesbetween(from, to).getminutes()   1,            minutes::minutes,             from -> from.withzone(datetimezone.utc)                        .withsecondofminute(0)                        .withmillisofsecond(0)),     hour(dimension.hour,          (from,           to) -> hours.hoursbetween(from, to).gethours()   1,          hours::hours,          from -> from.withzone(datetimezone.utc)                      .withminuteofhour(0)                      .withsecondofminute(0)                      .withmillisofsecond(0)),     day(dimension.day,         (from,          to) -> days.daysbetween(from, to).getdays()   1,         days::days,         from -> from.withzone(datetimezone.utc)                     .withtimeatstartofday()),     week(dimension.week,          (from,           to) -> weeks.weeksbetween(from, to).getweeks()   1,          weeks::weeks,          from -> from.withzone(datetimezone.utc)                      .withdayofweek(1)                      .withtimeatstartofday()),     month(dimension.month,           (from,            to) -> months.monthsbetween(from, to).getmonths()   1,           months::months,           from -> from.withzone(datetimezone.utc)                       .withdayofmonth(1)                       .withtimeatstartofday());      private dimension dimension;     private bifunction getnumberofpoints;     private function getperiodfromnbofinterval;     private function getstartofinterval;      private timeperiod(dimension dimension,                        bifunction getnumberofpoints,                        function getperiodfromnbofinterval,                        function getstartofinterval)     {         this.dimension = dimension;         this.getnumberofpoints = getnumberofpoints;         this.getperiodfromnbofinterval = getperiodfromnbofinterval;         this.getstartofinterval = getstartofinterval;     }      public dimension getdimension()     {         return dimension;     }      public int getnumberofpoints(datetime from,                                  datetime to)     {         return getnumberofpoints.apply(from, to);     }      public readableperiod getperiodfromnbofinterval(int nbofinterval)     {         return getperiodfromnbofinterval.apply(nbofinterval);     }      public datetime getstartofinterval(datetime from)     {         return getstartofinterval.apply(from);     } }

通过枚举,我就能够很容易地修改代码,允许用户给图表数据点指定时间段。

原来是这样调用:

for (int i = 0; i <= days.daysbetween(from, to).getdays(); i  )

变成这样调用:

for (int i = 0; i < timeperiod.getnumberofpoints(from, to); i  )

支持getgraphdatapoints调用的usage analytics服务代码已经完成了,并且支持时间段。值得一提的是,它考虑了我之前说过的开放闭合原则。

展开全文
内容来源于互联网和用户投稿,文章中一旦含有亚博电竞手机版的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系亚博电竞手机版删除

最新文章

网站地图