Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring:将stradegy移动到编码还是保留在xml文件中?_Java_Spring_Dependency Injection_Inversion Of Control - Fatal编程技术网

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);
    }

}