java - 我们可以将下面的模式称为DI吗?

标签 java spring design-patterns

请原谅我的无知。我对 Java 还很陌生。我研究过Spring DI。我们提供的任何基于 xml 或注释的配置都将用于以声明方式注入(inject)依赖项。但是,我认为我们无法动态更改依赖项。

因此,我创建了以下示例代码,它可以通过扩展类路径来提供依赖项(未显示扩展类路径的代码)。我们可以称之为 DI 吗?

标记界面

public interface IRule {

}

扩展IRule的接口(interface)

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。客户端将被移交给 FooRuleImpletor 的实例,如下所示(带有从 xml 读取的类)。

RulesFactory rulesFactory = new RulesFactory();
IFooRule fooRule = rulesFactory.getRuleImplementation(clazz);

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

更新

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

最佳答案

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

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

The fundamental choice is between Service Locator and Dependency Injection. The first point is that both implementations provide the fundamental decoupling that's missing in the naive example - in both cases application code is independent of the concrete implementation of the service interface. The important difference between the two patterns is about how that implementation is provided to the application class. With service locator the application class asks for it explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.

The disadvantages are arguable因为与大多数模式一样,这取决于您的要求。因此,我将它们称为权衡。

在这种情况下,它们是主要优势(解耦)的结果。在进行模块化设计时,请记住最大限度地减少耦合,同时最大限度地提高内聚性。因此,请确保您没有创建太细粒度的模块。

列举一些权衡:

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

我的建议是,仅当您拥有具有多个实现的稳定接口(interface),或者至少您确定很快就会有另一个接口(interface)时,才使用它。只是不要为了以防万一有一天你的界面可能有另一种实现而去追求它。如果您这样做,您很可能会发现自己过度设计,而牺牲了编译时检查或 IDE 辅助等功能。

这是服务定位器和依赖注入(inject)模式的主要共同点。

关于java - 我们可以将下面的模式称为DI吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27254405/

相关文章:

java - 当使用 lambda 表达式而不是匿名内部类时,Spring 无法确定泛型类型

spring - tomcat + spring +quartz = 关闭错误

java - 关于集合访问器转换的模式

c# - 需要两个单例实例

design-patterns - 解释器模式示例

java - Activity 之间的Android数据检索

java - 在投影之间转换时,geotools 反转 WGS 的纬度/经度

java - getConnection 是否总是打开一个新连接?

java - 如何从 Java Spring 消费者应用程序调用 Java Spring 实用程序 jar

java - 在 TestLuck(概率)程序中计算平均值