我有多个实现接口并返回Object的类。
public interface DataFetcher {
Data getData(Info info);
}
public class Data {
private String name;
private String value;
}
@Component
public class DataPointA implements DataFetcher {
@Override
public Data getData(Info info) {
//..Do some processing
return new Data("SomeName", valueComputed);
}
}
现在,我有大约20个数据点,它们实现DataFetcher类并返回数据对象。
我将所有数据点自动连接到一个类,并根据某些条件使用某些数据点。
@Component
public class DataComputer {
@Autowired
private DataPointA dataPointA;
@Autowired
private DataPointB dataPointB;
.
.
.
public void computeData(String inputType, Info info) {
List<DataFetcher> dataFecthers;
switch(inputType) {
case "typeA" : dataFecthers = ImmutableList.of(dataPointA, dataPointB);
break;
.
.
.
case "typeD" : dataFecthers = ImmutableList.of(dataPointE, dataPointF, dataPointG);
break;
}
dataFetcher.forEach(dataPoint -> {
//Do some processing with dataPoint.getData(info)
})
}
}
可以看出,DataComputer类将具有依赖关系的完整列表,这些依赖关系可能变得难以管理。另外,基于输入类型要使用的数据点也是事先已知的,因此可以将其提取出来。这是我做的尝试:
@Component
public class DataComputationPointDecider {
@Autowired
private DataPointA dataPointA;
@Autowired
private DataPointB dataPointB;
.
.
.
@Bean
public Map<String, List<DataFetcher>> getDataComputationPoints() {
return new ImmutableMap.Builder<String, List<DataFetcher>>()
.put("typeA", ImmutableList.of(dataPointA, dataPointB))
.put("typeD", ImmutableList.of(dataPointE, dataPointF, dataPointG))
.build();
}
}
然后,我的DataComputer依赖关系减少了:
@Component
public class DataComputer {
@Autowired
private Map<String, List<DataFetcher>> dataComputationPoints;
public void computeData(String inputType, Info info) {
List<DataFetcher> dataFecthers = dataComputationPoints.get(inputType);
dataFetcher.forEach(dataPoint -> {
//Do some processing with dataPoint.getData(info)
})
}
}
有没有更好的方法来设计这个?
最佳答案
我认为您的方法没有什么大不了的。但我建议另一种选择。
您可以使inputType
决定或说出它可以处理的输入类型,而不是维护用DataFetcher
列表映射DataFetcher
的映射。
但这需要将DataFetcher
的接口更改为
public interface DataFetcher {
boolean canHandle(String inputType);
Data getData(Info info);
}
实现看起来像
@Component
public class DataPointA implements DataFetcher {
@Override
boolean canHandle(String inputType) {
return "typeA".equals(inputType);
}
@Override
public Data getData(Info info) {
//..Do some processing
return new Data("SomeName", valueComputed);
}
}
然后,您可以将所有
DataFetcher
注入为一个列表(不必为每个列表添加一个@Autowired
字段)并将其处理为@Autowired
List<DataFetcher> dataFetchers;
...
dataFetchers.stream()
.filter(dataFetcher -> dataFetcher.canHandle(inputType))
.forEach(dataFetcher.getData(info));
优点:
在当前方法中,如果添加新的
DataFetcher
实现,则需要添加@AutoWired
字段/成员并修改(getDataComputationPoints)映射。但是,有了它,DataFetcher
可以处理的inputTypes本身就被指定了,因此您只需要为新的输入类型添加新的类。参考
Autowire reference beans into list by type
更新:
缺点
输入类型在类内部指定,这意味着您无法轻松找到给定输入类型的
DataFetchers
(数据点)列表。如果需要删除对inputType的支持,则再次需要访问每个实现(从
canHandle
中删除该inputType)。在您的方法中,它只是删除一个地图条目。