【问题标题】:Cons of static utility classes in java?java中静态实用程序类的缺点?
【发布时间】:2011-07-10 15:58:59
【问题描述】:

创建静态实用程序类有什么缺点?我做得越多,我就越觉得它们非常有用。我知道他们缺乏面向对象的设计,但我仍然可能比我应该更爱他们。使用它们还有其他缺点吗?

【问题讨论】:

标签: java static


【解决方案1】:

在正确的上下文中,它们没有任何问题。如果您有独立的、无状态的方法(例如在java.lang.Math 中找到的方法),那么静态类是它们的理想场所。它们在一个类中的唯一原因是因为 Java 没有独立方法的概念。

【讨论】:

  • 我明白了,这是一个公平的观点。如果我在静态类中添加对象存储,让它更像是一个静态单例呢?
  • @Aedon:一旦它变成有状态的,那么单元测试就会变得困难。我会将我的建议限制在“纯”方法上。
【解决方案2】:

IMO 的主要缺点是无法使用大多数模拟框架来模拟此类实用方法的实现,以便使用这些实用方法对某些类进行单元测试。

例如,使用System.currentTimeMillis() 很容易得到当前时间。但是当你必须测试一个使用当前时间做一些工作的类时,不可能模拟该方法以使其返回特定的时间点。使用实现Clock 接口的对象并将其注入到对象中进行测试会更容易:您可以创建一个模拟时钟实现,在被要求获取当前时间时返回特定日期。

【讨论】:

  • 你能解释一下这个说法吗?是什么让它们难以进行单元测试?
  • currentTimeMillis() 方法确实如此。但就像@Oli Charlesworth 所说,Math api 将一成不变。
  • 是的,但同样适用。假设如果某个计算值的余弦等于 0.5,则在方法的中间有一个极端情况。模拟一个 MathEngine 对象并使其返回 0.5 来测试极端情况要比找到一组输入值要容易得多,这将使 Math.cos 方法在所有先前的计算之后返回 0.5。特别是如果之前的计算取决于当前时间:-)
  • @JB:这听起来很做作!如果被测对象依赖于与其实际生成的输入相对应的cos 调用结果,会发生什么情况?
  • 如果被测对象知道cos的结果是0.5,它就没有理由调用Math.cos。当它调用 Math.cos 时,它期望得到一个有效的 cosinus 值,但这个值可能是任何值。无论如何,测试的重点不是让方法做不可能的事情。它的重点是测试一种方法并涵盖所有可能的路径。
【解决方案3】:

我之前在一篇帖子中谈到过这个问题,你可以找到here

使用静态方法的主要问题是:

  1. 其他发帖人指出的可模拟性。
  2. 可以在应用程序中加载静态类的多个版本,具体取决于为类加载器的整个层次结构配置的类加载器层次结构和类路径。 (第三个因素也是类加载器是否配置为父优先或子优先)使测试和调试成为一场噩梦。
  3. 不能继承静态方法。因此违反了OCP (Open Closed Principle),即静态方法不可扩展。查看 Log4J 以了解静态方法的典型问题。
  4. 静态方法不适用于Interface Segregation PrincipleStrategy 模式的应用。如果不求助于大量带有“if 条件”的大量手写代码,就不可能根据个别用例对类似算法进行替代实现。

但是,如果方法本身不太麻烦并且几乎可以预测(即对实现的不同变体等没有太多要求),那么静态方法没有理由不符合要求。所以,这个故事的寓意是使用它,但要注意副作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2013-08-20
    • 2011-01-29
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多