我们可以调用以下模式DI吗?

时间:2014-12-02 16:36:53

标签: java spring design-patterns

请原谅我的无知。我是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);

这种模式的名称是什么?我们可以称之为依赖注入吗?

更新

我还想知道这种模式的潜在缺点,如果有的话。是否有可以使用的经过充分测试的替代模式?

1 个答案:

答案 0 :(得分:3)

您所描述的更像是服务定位器,您可以使用它来解决依赖关系。但依赖本身并未注入 - 没有控制反转,您可以通过rulesFactory.getRuleImplementation(clazz)调用控制依赖关系解析。

来自Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern(我建议您阅读):

  

基本选择是服务定位器和依赖注入之间。第一点是两个实现都提供了天真示例中缺少的基本解耦 - 在这两种情况下,应用程序代码都独立于服务接口的具体实现。这两种模式之间的重要区别在于如何为应用程序类提供该实现。使用服务定位器,应用程序类通过发送给定位器的消息明确地请求它。使用注入没有明确的请求,服务出现在应用程序类中 - 因此控制反转。

The disadvantages are arguable因为大多数模式都取决于您的要求。因此,我称之为权衡取舍。

在这种情况下,它们是主要优势(解耦)的结果。在设计模块化时,请记住最小化耦合,但也要最大化内聚力。因此,请确保您没有创建太精细的模块。

列举一些权衡:

  • 这会使您的代码不那么清晰。
  • 使维护更加困难。
  • 您丢失了一些编译时检查,这意味着潜在的运行时错误。

我的建议是只有在你有几个实现的稳定接口时才使用它,或者至少你确定很快会有另一个实现。只是不要为了以防万一有一天可能有你的界面的另一个实现。如果你这样做,你很可能会发现自己过度工程,而不考虑编译时检查或IDE辅助工具。

这主要是服务定位器和依赖注入模式的共同基础。