Java Spring ServiceLocator 还是纯工厂模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18654668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring ServiceLocator or pure factory pattern?
提问by Kakawait
99% of my dependency is manage with DI pattern via @Autowired Spring annotation.
我 99% 的依赖是通过 @Autowired Spring 注释使用 DI 模式管理的。
Nevertheless in a particular scenario, I can't determine which implementation to be used until run-time.
尽管如此,在特定情况下,我无法确定要使用哪个实现,直到运行时。
The most known case, is the multiple implementation of parsers.
最著名的情况是解析器的多重实现。
The first solution is to used multiple @Autowired (ugly mode)
第一种解决方案是使用多个@Autowired(丑模式)
Interface Parser {
<T> T parse();
}
@Component("JsonParser")
class JsonParser implements Parser {
...
}
@Component("XmlParser")
class XmlParser implements Parser {
...
}
class MyService {
@Autowired
@Qualifier("XmlParser")
Parser xmlParser;
@Autowired
@Qualifier("JsonParser")
Parser jsonParser;
...
}
But if I have a large number of implementation that can be not acceptable.
但是如果我有大量的执行那是不能接受的。
The second solution is to used ServiceLocator from Spring
第二种解决方案是使用 Spring 中的 ServiceLocator
interface ParserServiceLocatorFactory {
public Parser getParser(String parserName);
}
interface Parser {
<T> T parse();
}
@Component("JsonParser")
class JsonParser implements Parser {
...
}
@Component("XmlParser")
class XmlParser implements Parser {
...
}
class MyService {
@Autowired
ServiceFactory parserServiceLocatorFactory;
void exampleMethod() {
Parser xmlParser = parserServiceLocatorFactory.getParser("XmlParser");
}
}
This way to do seems right to me but compared with the third solution?
这种方式对我来说似乎是正确的,但与第三种解决方案相比?
The third solution is to used pure factory pattern and inject it.
第三种解决方案是使用纯工厂模式并注入它。
@Component
public ParserFactory {
Parser getParser(String parserName) {
...
}
}
interface Parser {
<T> T parse();
}
@Component("JsonParser")
class JsonParser implements Parser {
...
}
@Component("XmlParser")
class XmlParser implements Parser {
...
}
class MyService {
@Autowired
ParserFactory parserFactory
void exampleMethod() {
Parser xmlParser = parserFactory.getParser("XmlParser");
}
}
If you have pro/con for the previous solutions, or even better solution for my problem?
如果您对以前的解决方案有赞成/反对意见,或者对我的问题有更好的解决方案?
PS: it's pseudo code I may miss some small things :)
PS:这是伪代码,我可能会错过一些小东西:)
采纳答案by Maksym Demidas
As an option you can use list injection:
作为一个选项,您可以使用列表注入:
public class SomeService {
@Autowired
private List<Parser> parsers;
public doSomethingWithParser(...) {
...
Parser parser = getParser(JsonParser.class);
parser.parse(...);
...
}
private Parser getParser(Class<Parser> targetClass) {
Parser result = null;
for(Parser parser : parsers) {
if(parser.getClass().equals(targetClass)){
result = parser;
}
}
return transformer;
}
}
Even better, you can add Parser.isCompatibleWith(SomeInput input)
method to simplify paser detection code.
更好的是,您可以添加Parser.isCompatibleWith(SomeInput input)
方法来简化paser 检测代码。
回答by Kingz
Below is an example of a service locator class. This returns a service for the given ID from the service registry. The registry is a MAP which is autowired as shown. This is a working example from a production system:
以下是服务定位器类的示例。这将从服务注册表返回给定 ID 的服务。注册表是一个 MAP,如图所示自动装配。这是来自生产系统的工作示例:
@Service
public class MyServiceLocator {
@Autowired
private Map<String, MyService> myServiceRegistry;
/**
* Service locator to find the right Domain service to interact with the requested data store
*
* @param serviceID
* @return
*/
public MyService locateServiceFor(String serviceID) {
//Using the Given string 'serviceID' as key, lookup the service from the Registry
return myServiceRegistry.get(serviceID);
}