对于项目,我们有一个Controller / Service / DAO架构.我们实现了对不同提供者API的调用,因此我们在每个控制器类中都得到了一些这样的样板代码:
enum { PARTNER_A,PARTNER_B,PARTNER_C } public class MyController { @Resource PartnerASearchService partnerASearchService; @Resource PartnerBSearchService partnerBSearchService; @Resource PartnerCSearchService partnerCSearchService; public search(InputForm form) { switch(form.getPartnerName()) { case PARTNER_A: partnerASearchService.search(); break; case PARTNER_B: partnerBSearchService.search(); break; case PARTNER_C: partnerCSearchService.search(); break; } } public otherMethod(InputForm form) { switch(form.getProvider()) { case PARTNER_A: partnerAOtherService.otherMethod(); break; case PARTNER_B: partnerBOtherService.otherMethod(); break; case PARTNER_C: partnerCOtherService.otherMethod(); break; } } }
我可以使用哪种设计模式来摆脱每个控制器中的这个开关?我希望代码类似于下面的代码:
public class MyController { @Resource ServiceStrategy serviceStrategy; public search(InputForm form){ serviceStrategy.search(form.getPartnerName()) // or serviceStrategy.invoke(SEARCH,form.getPartnerName()) } public otherMethod(InputForm form){ serviceStrategy.other(form.getPartnerName()) // or serviceStrategy.invoke(OTHER,form.getPartnerName()) } }
让serviceStrategy决定调用哪个服务实现,从而将伙伴的开关放在一个地方.
我已经使用了“策略”一词,因为我被告知这种设计模式可以实现,但我不确定使用它的最佳方式,或者是否有更好的方法来解决这个问题.
编辑:我已经更新了问题,因为术语提供者具有误导性.我在输入表单中的内容是我们执行请求的合作伙伴的名称.我想要一个模式,根据表单中的合作伙伴名称决定使用哪个正确的实现(几个服务中的哪一个)
解决方法
通常,表单不需要知道“提供者”将处理它的内容.相反,提供者应该能够解释他们可以处理哪种输入.
我建议使用一种形式的责任链(将重构条件替换为多态性),它看起来像这样(为简单起见,Groovy):
interface ProviderService { boolean accepts(InputForm form) void invoke(String foo,InputForm form) void other(InputForm form) }
ProviderService实现的每个实现都接受以指示它是否可以处理特定表单,并且您的控制器存储List< ProviderService>服务而不是个人参考.然后,当您需要处理表单时,您可以使用:
ProviderService service = services.find { it.accepts(form) } // error handling if no service found service.other(form)
有关在主框架中使用的此模式的综合示例,请参见the Spring conversion service.