2012-02-20 61 views
24

我是一个Java开发谁是开始把握依赖注射的全部功能,并且它突然对我说明白没有办法注入一个静态方法。所以这让我想到:是静态方法DI反模式?静态方法是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(); 
    } 
} 

...但我不问如何注入现有的静态方法......如果我所有的代码(从这个角度来看)都会接受DI的概念,我会问我是否应该停止写下它们。

而且,我看到很多类似的相关问题,这一点,但无法找到问同样的问题完全匹配。如果你发现这确实是另一个问题,请给我指出,我会自己解决这个问题(请不要只是关闭它!)。

回答

38

静态方法适用于没有关联状态的事物。一些工厂方法,“纯功能”方法如Math.sin等都是完全可以接受的静态方法。 java.lang.Mathjava.util.Collections有很多很好的可以接受的静态方法的例子。

幸运的是,这些方法不需要依赖注入或与这些事物交互;他们并不是特别难以测试。他们没有需要嘲笑或任何事情的依赖关系。另一方面,静态或与静态相关的静态方法是完全邪恶的。 的反模式。

它经常有助于定义的方法为无状态(因此一个合法的静态方法),当且仅当,它总是返回上等效的输入等效输出。这表明例如,数据库查询和文件系统I/O使得方法成为有状态的,因为它们的输出将根据文件系统或数据库中的内容而变化。

+0

所以,如果我有一个叫做'嘶嘶声()'方法,并在其中我做一个静态调用到'Widget.buzz()'方法,它击中一个数据库,并发出各种变化,以我的本地文件系统,那么如何测试'fizz()'而不用调用'Widget.buzz()'调用所有的巨大变化呢?我的观点是,我认为我应该停止完全编写静态方法,以便我可以在运行时注入正确的'Widget'对象(正常vs模拟),然后控制哪个“版本”的buzz()会触发。思考? – IAmYourFaja 2012-02-20 20:08:13

+0

'Widget.buzz()'具有关联的静态状态 - 数据库和隐式的整个文件系统。这是邪恶的。 'fizz'可能需要一个'Widget'参数,并且你会嘲笑一个'Widget'来测试'fizz'。 – 2012-02-20 20:11:28

+0

啊,我从来没有想过数据库或文件系统是有状态的。你用什么标准来定义“有状态”?我认为这是我误解的根源。 – IAmYourFaja 2012-02-20 20:15:50

2

不平凡的静态方法与依赖注入兼容。简单地让他们成为单身人士的实例方法。