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