为什么使用单例而不是静态方法?

时间:2010-05-04 12:03:07

标签: java design-patterns singleton

我从来没有找到关于助手/实用程序类的这些简单问题的好答案:

为什么要创建单例(无状态)而不是使用静态方法?

如果对象没有状态,为什么需要对象实例?

8 个答案:

答案 0 :(得分:75)

通常,单例用于向应用程序引入某种全局状态。 (说实话,这通常是非常必要的,但这是另一个时间的主题。)

但是,有一些极端情况甚至无状态单例可能有用:

  • 您希望在可预见的未来将其延伸至州。
  • 对于某些特定的技术原因,您需要对象实例。例如:C#lock或Java {{1}的同步对象声明。
  • 您需要继承,即您希望能够使用相同的接口,但使用不同的实现轻松地将您的单件替换为另一个。
    示例:Java中的synchronized方法将返回单例其确切类型取决于系统。
  • 您想要sentinel value引用相等。例如:C#中的Toolkit.getDefaultToolkit()

答案 1 :(得分:37)

我可以看到使用无状态单例而不是静态方法类的情况,即Dependency Injection

如果你有一个直接使用的辅助类实用程序函数,它会创建一个隐藏的依赖项;你无法控制谁可以使用它,或者在哪里。通过无状态单例实例注入相同的帮助器类,可以控制它的使用位置和方式,并在需要时替换它/ mock it / etc.

使其成为单例实例只是确保您不再分配超出必要类型的任何对象(因为您只需要一个)。

答案 2 :(得分:14)

实际上我发现这里没有提到另一个答案:静态方法更难测试。

似乎大多数测试框架都非常适合模拟实例方法,但是其中许多测试框架并没有以一种不错的方式处理静态方法的模拟。

答案 3 :(得分:6)

答案 4 :(得分:4)

在使用哪一个之间存在权衡。单身人士可能有也可能没有国家,他们指的是对象。如果它们不保持状态并且仅用于全局访问,则静态更好,因为这些方法将更快。但是如果你想利用对象和OOP概念(继承多态),那么单例就更好了。

考虑一个例子:java.lang.Runtime是java中的单例类。此类允许每个JVM的不同实现。每个JVM的实现是单一的。如果这个类是静态的,我们就不能通过基于JVM的不同实现。

我发现此链接非常有用:http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

希望它有所帮助!!

答案 5 :(得分:2)

对我来说"想要对象状态使用Singleton,旺旺函数使用静态方法"

这取决于你想要什么。每当你想要对象状态(例如像Null状态而不是null或默认状态的多态)时,单例是你的合适选择,而静态方法在你需要函数时使用(接收输入然后返回输出)。

我建议对于单例情况,它在实例化后应该始终是相同的状态。它既不应该是可克隆的,也不应该接收任何值(除了文件中的静态配置,例如java中的属性文件)。

P.S。这两者之间的性能在几毫秒之间是不同的,因此首先关注架构

答案 6 :(得分:1)

Singleton不是无状态的,它拥有全局状态。

我可以想到使用Singleton的一些原因是:

  • 避免内存泄漏
  • 为应用程序中的所有模块提供相同的状态,例如数据库连接

答案 7 :(得分:0)

根据 GoF 的书设计模式,“单例”一章,与单例相比,类操作具有以下缺点(我的粗体强调):

<块引用>
  1. 比类操作更灵活。另一种封装单例功能的方法是使用类操作(即 C++ 中的静态成员函数或 Smalltalk 中的类方法)。但是这两种语言技术都使得很难改变设计以允许一个类的多个实例。而且,C++ 中的静态成员函数从来都不是虚拟的,所以子类不能覆盖它们多态。