First, please let me introduce a minimal scene demo to explain the problem.
Let's say i have a strategy pattern interface.
public interface CollectAlgorithm<T> {
public List<T> collect();
}
And a implementation of this strategy, the ConcreteAlgorithm
.
public class ConcreteAlgorithm implements CollectAlgorithm<Integer> {
@Resource
QueryService queryService;
@Override
public List<Integer> collect() {
// dummy ...
return Lists.newArrayList();
}
}
As you can see, the implementation depend on some query operation provided by a @Service
component.
The ConcreteAlgorithm
class will be created by new
in some places, then the collect
method will be called.
I've read some related link like Spring @Autowired on a class new instance, and know that the above code cannot work, since the instance created by new
has a @Resource
annotated member.
I'm new to Spring/Java, and i wonder if there are some ways, or different design, to make scene like above work.
I've thought about use factory method, but it seems that it will involve many unchecked type assignment since i provided a generic interface.
UPDATE
To make it more clear, i add some detail about the problem.
I provide a RPC service for some consumers, with an interface like:
public interface TemplateRecommendService {
List<Long> recommendTemplate(TemplateRecommendDTO recommendDTO);
}
@Service
public class TemplateRecommandServiceImpl implements TemplateRecommendService {
@Override
public List<Long> recommendTemplate(TemplateRecommendDTO recommendDTO) {
TemplateRecommendContext context = TemplateRecommendContextFactory.getContext(recommendDTO.getBizType());
return context.process(recommendDTO);
}
}
As you can see, i will create different context by a user pass field, which represent different recommendation strategy. All the context should return List<Long>
, but the pipeline inside context is totally different with each other.
Generally there are three main stage of the context process pipeline. Each stage's logic might be complicated and varied. So there exists another layer of strategy pattern.
public abstract class TemplateRecommendContextImpl<CollectOut, PredictOut> implements TemplateRecommendContext {
private CollectAlgorithm<CollectOut> collectAlgorithm;
private PredictAlgorithm<CollectOut, PredictOut> predictAlgorithm;
private PostProcessRule<PredictOut> postProcessRule;
protected List<CollectOut> collect(TemplateRecommendDTO recommendDTO){
return collectAlgorithm.collect(recommendDTO);
}
protected List<PredictOut> predict(TemplateRecommendDTO recommendDTO, List<CollectOut> predictIn){
return predictAlgorithm.predict(recommendDTO, predictIn);
}
protected List<Long> postProcess(TemplateRecommendDTO recommendDTO, List<PredictOut> postProcessIn){
return postProcessRule.postProcess(recommendDTO, postProcessIn);
}
public /*final*/ List<Long> process(TemplateRecommendDTO recommendDTO){
// pipeline:
// dataCollect -> CollectOut -> predict -> Precision -> postProcess -> Final
List<CollectOut> collectOuts = collect(recommendDTO);
List<PredictOut> predictOuts = predict(recommendDTO, collectOuts);
return postProcess(recommendDTO, predictOuts);
}
}
As for one specific RecommendContext
, its creation likes below:
public class ConcreteContextImpl extends TemplateRecommendContextImpl<GenericTempDO, Long> {
// collectOut, predictOut
ConcreteContextImpl(){
super();
setCollectAlgorithm(new ShopDecorateCrowdCollect());
setPredictAlgorithm(new ShopDecorateCrowdPredict());
setPostProcessRule(new ShopDecorateCrowdPostProcess());
}
}