使用Java枚举类优化工厂方法
背景
最近在工作中遇到一个需求,需要把不同的统计报表导出成csv文件,经过一系列抽象过后,发现不同的导出类型,还是需要不同的service来进行处理,这样就会导致工厂方法存在大量的
if else
或者switch case
语句,这样看起来代码非常臃肿,不便于后面维护,于是使用枚举类进行重构,在此记录一下。
场景
在没有进行改动的时候,代码是这样的:
private Collection<String[]> initData(ExportParam exportParam, Exportkey v) {
Collection<String[]> data = null;
switch (v) {
case CONTENT_HISTORY_LIST:
data = applicationContext.getBean(HistoryContentCsvDataServiceImpl.class).initData(exportParam);
break;
case CONTENT_CAPACITY_STATS:
data = applicationContext.getBean(ContentCapacityStatsServiceImpl.class).initData(exportParam);
break;
case CONTENT_AMOUNT_STATS:
data = applicationContext.getBean(ContentAmountStatsServiceImpl.class).initData(exportParam);
break;
case DEVICE_ONLINE_RATE_STATS:
data = applicationContext.getBean(DeviceOnlineRateServiceImpl.class).initData(exportParam);
break;
case DEVICE_ONLINE_DETAIL_LIST:
data = applicationContext.getBean(DeviceOnlineDetailServiceImpl.class).initData(exportParam);
break;
case PLAY_COUNT_CONTENT_STATS:
data = applicationContext.getBean(PlayCountContentStatsServiceImpl.class).initData(exportParam);
break;
case PLAY_COUNT_DEVICE_STATS:
data = applicationContext.getBean(PlayCountDeviceStatsServiceImpl.class).initData(exportParam);
break;
... 省略部分代码
}
return data;
}
这里面使用了switch语句进行判断,不同的case拿到不同的bean,导致代码很长,于是对Exportkey
这个枚举类进行改造。
public enum Exportkey {
CONTENT_HISTORY_LIST,
CONTENT_CAPACITY_STATS,
CONTENT_AMOUNT_STATS,
DEVICE_ONLINE_RATE_STATS,
DEVICE_ONLINE_DETAIL_LIST,
PLAY_COUNT_CONTENT_STATS,
PLAY_RECORD_CONTENT_DETAIL_STATS,
PLAY_COUNT_DEVICE_STATS,
...
}
需要知道,枚举类是可以定义抽象方法的,枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类(因为系统自动会为它添加abstract关键字),但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。
经过改造后的导出枚举类如下:
public enum Exportkey {
CONTENT_HISTORY_LIST {
@Override
public CsvDataService create() {
return SpringUtils.getBean(HistoryContentCsvDataServiceImpl.class);
}
},
CONTENT_CAPACITY_STATS {
@Override
public CsvDataService create() {
return SpringUtils.getBean(ContentCapacityStatsServiceImpl.class);
}
},
CONTENT_AMOUNT_STATS {
@Override
public CsvDataService create() {
return SpringUtils.getBean(ContentAmountStatsServiceImpl.class);
}
},
PLAY_COUNT_CONTENT_STATS {
@Override
public CsvDataService create() {
return SpringUtils.getBean(PlayCountContentStatsServiceImpl.class);
}
},
...
public abstract CsvDataService create();
}
定义了一个抽象的create()方法,在每个枚举值中提供实现,这样我们原先的方法就不用switch了,变成了一行代码,如下:
private Collection<String[]> initData(ExportParam exportParam, Exportkey key) {
return key.create().initData(exportParam);
}