请原谅我的无知。我是Java新手。我研究过Spring DI。我们提供的基于xml或注释的配置将用于以声明方式注入依赖项。但是,我认为我们无法动态更改依赖关系。
因此,我创建了以下示例代码,它可以通过扩展类路径来提供依赖关系(未显示扩展类路径的代码)。我们可以称之为DI吗?
标记界面
public interface IRule {
}
扩展IRule的界面
public interface IFooRule extends IRule {
public boolean validate(String json);
}
实施IFooRule的类
public class FooRuleImplemetor {
private FooRuleImplemetor implementor;
private FooRuleImplemetor() {
}
public boolean validateRule(String json) {
--Business Logic--
}
public static synchronized FooRuleImplemetor getInstance() {
if (implementor == null) {
implementor = new FooRuleImplemetor();
}
return implementor;
}
}
规则工厂。几乎所有IS-A IRule
类的工厂类public class RulesFactory {
public <T extends IRule> T getRuleImplementation(String clazz) {
try {
Class<?> ruleObject = Class.forName(clazz);
Method factoryMethod = ruleObject.getMethod("getInstance");
return (T) factoryMethod.invoke(null);
} catch (ClassNotFoundException e) {
logger.error("ClassNotFoundException", e);
} catch (IllegalAccessException e) {
logger.error("IllegalAccessException", e);
} catch (SecurityException e) {
logger.error("SecurityException", e);
} catch (NoSuchMethodException e) {
logger.error("NoSuchMethodException", e);
} catch (IllegalArgumentException e) {
logger.error("IllegalArgumentException", e);
} catch (InvocationTargetException e) {
logger.error("InvocationTargetException", e);
}
return null;
}
}
XML配置(仅限部分内容)
<rule>
<action class="com.mycompany.FooRuleImplemetor">
<rule>
将动态读取不属于类路径的xml。客户端将被移交给FooRuleImplemetor的一个实例,如下所示(从xml读取类)。
RulesFactory rulesFactory = new RulesFactory();
IFooRule fooRule = rulesFactory.getRuleImplementation(clazz);
这种模式的名称是什么?我们可以称之为依赖注入吗?
更新
我还想知道这种模式的潜在缺点,如果有的话。是否有可以使用的经过充分测试的替代模式?
答案 0 :(得分:3)
您所描述的更像是服务定位器,您可以使用它来解决依赖关系。但依赖本身并未注入 - 没有控制反转,您可以通过rulesFactory.getRuleImplementation(clazz)
调用控制依赖关系解析。
来自Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern(我建议您阅读):
基本选择是服务定位器和依赖注入之间。第一点是两个实现都提供了天真示例中缺少的基本解耦 - 在这两种情况下,应用程序代码都独立于服务接口的具体实现。这两种模式之间的重要区别在于如何为应用程序类提供该实现。使用服务定位器,应用程序类通过发送给定位器的消息明确地请求它。使用注入没有明确的请求,服务出现在应用程序类中 - 因此控制反转。
The disadvantages are arguable因为大多数模式都取决于您的要求。因此,我称之为权衡取舍。
在这种情况下,它们是主要优势(解耦)的结果。在设计模块化时,请记住最小化耦合,但也要最大化内聚力。因此,请确保您没有创建太精细的模块。
列举一些权衡:
我的建议是只有在你有几个实现的稳定接口时才使用它,或者至少你确定很快会有另一个实现。只是不要为了以防万一有一天可能有你的界面的另一个实现。如果你这样做,你很可能会发现自己过度工程,而不考虑编译时检查或IDE辅助工具。
这主要是服务定位器和依赖注入模式的共同基础。