Java Spring:将stradegy移动到编码还是保留在xml文件中?
我有一个语言翻译界面,定义如下Java Spring:将stradegy移动到编码还是保留在xml文件中?,java,spring,dependency-injection,inversion-of-control,Java,Spring,Dependency Injection,Inversion Of Control,我有一个语言翻译界面,定义如下 public interface TranslationService { public TranslationResult translate(TranslationRequeset req); public int maxTranslatableCount(); } 使用Google、Bing等实现该界面的方法如下: public class BingTranslationServiceImpl implements TranslationServi
public interface TranslationService {
public TranslationResult translate(TranslationRequeset req);
public int maxTranslatableCount();
}
使用Google、Bing等实现该界面的方法如下:
public class BingTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 10000;}
}
public class GoogleTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 2000;}
}
public class FooTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 50000;}
}
然后,在我们的客户机代码中,如果某个特定的翻译服务失败,我们必须执行故障转移
为了实现这一点,我引入了一个“TranslationProxy”,在下面的列表中定义故障转移策略:
public class BingTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 10000;}
}
public class GoogleTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 2000;}
}
public class FooTranslationServiceImpl implements TranslationService {
public TranslationResult translate(TranslationRequeset req){}
public int maxTranslatableCount(){return 50000;}
}
基本上,如果某个特定的服务无法翻译,那么这个函数将遍历列表
public class TranslationProxy implements TranslationService {
private List<TranslationService> services;
TranslationResult translate(TranslationRequeset req) {
//
}
public List<TranslationBusinessLogic> getServices() {
return services;
}
public void setServices(List<TranslationBusinessLogic> services) {
this.services = services;
}
}
另一个地方:
class SomeAnotherBusinessLogic {
@Autowired
@Qualified("translationProxy_Foo_Bing_Google")
private TranslationService translationService;
public void some_method_which_uses_translation_with_different_failover_stradegy() {
result = translationService(request);
}
}
这不是实现故障切换跨段的最干净的方法吗?
有人要求我将故障转移段移到客户机代码中
类似于以下内容(在春天是不可能的):
这里的“SomeAnnotationDefiningTheStradegy”是一个注释,它将用参数中定义的bean填充列表。从功能上讲,我看不出您的两个选项之间有什么区别。很明显,您实际上是在使用一个
servicecordinator
,您称之为TranslationProxy
来处理TranslationService
实现列表,并最终使用。定义代理的多个排列看起来确实有点单调乏味,这些排列仅因它们引用的TranslationService
实现列表不同,但是正如您所指出的,您需要一些定制的Spring魔术来实现第二个选项,除非您要注入所需的服务(在您的示例中是“bing”和“google”)与代理一起进入业务逻辑bean,然后将列表中的那些服务传递给代理(而不是在配置时将它们注入代理)。从这个意义上讲,您仍然使用“策略模式”但是您的策略容器现在只是在运行时传递的列表,而不是在配置期间在代理中引用的列表。这里可能有一些更优雅的东西,但实际上,可以说你听起来像是在“搬家”。我会再考虑一下。这是一个有趣的问题 首先,我建议您创建一个包含所有翻译服务的枚举(enum TranslationService Provider{BING,GOOGLE,FOO}
),并使用它代替字符串。向TranslationService
接口返回提供程序(TranslationServiceProvider getProvider()
)添加方法也很有用
我认为,最直接的选择是:
class SomeAnotherBusinessLogic {
private TranslationService translationService;
@Autowired
public void setTranslationService(TranslationDecider translationDecider) {
translationService = translationDecider.getProxyFor(
TranslationServiceProvider.BING, TranslationServiceProvider.FOO);
}
...
}
@Component
public class TranslationDeciderImpl implements TranslationDecider {
@Autowired
private List<TranslationService> translationServices;
public TranslationProxy getProxyFor(TranslationServiceProvider ... providers) {
List<TranslationService> services = // translationServices filtered using getProvider()
return new TranslationProxy(services);
}
}
class SomeAnotherBusinessLogic{
私人翻译服务;
@自动连线
公共无效设置TranslationService(TranslationDecider TranslationDecider){
translationService=translationDecider.getProxyFor(
TranslationServiceProvider.BING、TranslationServiceProvider.FOO);
}
...
}
@组成部分
公共类TranslationDeciderImpl实现TranslationDecider{
@自动连线
私有列表翻译服务;
公共TranslationProxy getProxyFor(TranslationServiceProvider…提供程序){
列表服务=//使用getProvider()筛选的translationServices
返回新的TranslationProxy(服务);
}
}
TranslationProxy
不由Spring管理,但可能不是必需的。如果是,则需要一个TranslationProxyFactory
。+1另一个好选项。同样,上述所有操作在执行过程中几乎相同。这取决于OP想要如何构造它。当添加第四个简单翻译服务时,为不同(简单)翻译服务创建枚举会导致代码更改。问题是对故障切换策略实施代码更改,而不是单个翻译服务。
class SomeAnotherBusinessLogic {
@Autowired
@Qualified("translationProxy_Foo_Bing_Google")
private TranslationService translationService;
public void some_method_which_uses_translation_with_different_failover_stradegy() {
result = translationService(request);
}
}
class SomeBusinessLogic {
@Autowired
@SomeAnnotationDefiningTheStradegy("bing","google")
private TranslationService translationService;
public void some_method_which_uses_translation() {
result = translationService(request);
}
class SomeAnotherBusinessLogic {
private TranslationService translationService;
@Autowired
public void setTranslationService(TranslationDecider translationDecider) {
translationService = translationDecider.getProxyFor(
TranslationServiceProvider.BING, TranslationServiceProvider.FOO);
}
...
}
@Component
public class TranslationDeciderImpl implements TranslationDecider {
@Autowired
private List<TranslationService> translationServices;
public TranslationProxy getProxyFor(TranslationServiceProvider ... providers) {
List<TranslationService> services = // translationServices filtered using getProvider()
return new TranslationProxy(services);
}
}