静态方法是DI反模式吗?

IAm*_*aja 33 java static-methods dependency-injection mocking

我是一名Java开发人员,他开始掌握依赖注入的全部功能,我突然意识到没有办法注入静态方法.所以它让我思考:静态方法DI反模式?

更重要的是:如果我要接受依赖注入,这是否意味着我需要停止编写静态方法?我问,因为没有办法在单元测试中模拟它们并注入模拟静态,这对我来说是一个巨大的转折点.

编辑:我知道"包装"和注入现有静态方法的常用方法是这样的:

public class Foo {
    public static void bar() { ... }
}

public interface FooWrapper {
    public void bar();
}

public class FooWrapperImpl implements FooWrapper {
    public void bar() {
        return Foo.bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

...但我不是在问如何注入一个现有的静态方法...我问我是否应该完全停止写它们,如果我所有的代码(从这一点开始)都要接受DI的概念.

此外,我看到很多与此类似的相关问题,但无法找到提出相同问题的完全匹配.如果你发现它确实是另一个问题的愚蠢,请指出我,我将自己关闭这个问题(请不要只是关闭它!).

Lou*_*man 42

静态方法适用于没有关联状态的事物. 一些工厂方法,"纯功能"方法Math.sin等等都是完全可接受的静态方法. java.lang.Math并且java.util.Collections有很多完美可接受的静态方法的例子.

幸运的是,这些方法不需要依赖注入,也不需要与这些东西进行交互; 他们并不难以测试.他们没有需要嘲笑或任何东西的依赖.

另一方面,静态或具有相关静态的静态方法是完全邪恶的.这一种反模式.

它常常有助于将方法定义为非有状态(因此是合法的静态方法),并且仅当它始终返回等效输入上的等效输出时.这清楚地表明,例如数据库查询和文件系统I/O使方法有状态,因为它们的输出将根据文件系统或数据库中的内容而变化.

  • 因此,如果我有一个名为 `fizz()` 的方法,并且我在其中静态调用了一个 `Widget.buzz()` 方法,该方法会访问数据库并对我的本地文件系统进行各种更改,那么我该怎么做?我测试了 `fizz()` 而不调用所有通过调用 `Widget.buzz()` 带来的巨大变化吗?我的观点是,我认为我应该完全停止编写静态方法,这样我就可以注入正确的 `Widget` 对象(普通 vs 模拟),然后控制在运行时触发的 `buzz()` 的“版本”。想法? (2认同)
  • -1问题是关于DI的,而不是一般而言静态方法的哲学。顺便说一句,数学有其邪恶的孪生兄弟StrictMath,因此希望能够彼此交换是合理的。答案是非平凡的静态方法与DI都不兼容,无论它们是否使用状态。 (2认同)