Spring ServiceLocator还是纯工厂模式?

99%的依赖关系通过@Autowired Spring注释来管理DI模式。

然而,在特定情况下,我无法确定在运行时使用哪个实现。

最着名的情况是解析器的多重实现。

第一个解决方案是使用多个@Autowired(丑陋模式)

Interface Parser {  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; ... } 

但是如果我有大量的实现,那是不可接受的。

第二个解决方案是使用Spring的ServiceLocator

 interface ParserServiceLocatorFactory { public Parser getParser(String parserName); } interface Parser {  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"); } } 

这种做法对我来说似乎是正确的,但与第三种解决方案相比较?

第三种解决方案是使用纯工厂模式并注入它。

 @Component public ParserFactory { Parser getParser(String parserName) { ... } } interface Parser {  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"); } } 

如果你有以前解决方案的pro / con,或者甚至更好地解决我的问题?

PS:这是伪代码我可能会错过一些小东西:)

作为选项,您可以使用列表注入:

 public class SomeService { @Autowired private List parsers; public doSomethingWithParser(...) { ... Parser parser = getParser(JsonParser.class); parser.parse(...); ... } private Parser getParser(Class targetClass) { Parser result = null; for(Parser parser : parsers) { if(parser.getClass().equals(targetClass)){ result = parser; } } return transformer; } } 

更好的是,您可以添加Parser.isCompatibleWith(SomeInput input)方法来简化paser检测代码。

下面是服务定位器类的示例。 这将从服务注册表返回给定ID的服务。 注册表是MAP,如图所示自动assembly。 这是生产系统的一个工作示例:

 @Service public class MyServiceLocator { @Autowired private Map 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); }