为什么使用单例而不是静态方法?
我从来没有find关于助手/实用程序类的简单问题的好答案:
为什么我会创build一个单身(无状态),而不是使用静态方法?
如果一个对象没有状态,为什么需要一个对象实例呢?
单例是用来向应用程序引入某种全局状态的。 如果它是无状态的,我也不会看到使用单例的情况,除非
- 你希望在可预见的未来将它扩展到状态
- 你需要一个特定的技术原因的对象实例 (例如,对于C#
lock
语句,虽然这已经是很牵强了),或者 - 你需要inheritance,也就是说,你希望能够使用相同的接口,但不同的实现,轻松地replace你的单身人士。 例如,Java中的
Toolkit.getDefaultToolkit()
方法将返回一个具有与系统相关的确切types的单例。
我可以看到使用无状态单例而不是静态方法类的情况,即dependency injection 。
如果你有一个直接使用的辅助类的效用函数,它会创build一个隐藏的依赖关系; 你无法控制谁可以使用它,或者在哪里。 通过无状态单例实例注入相同的帮助类,可以控制它在哪里以及如何使用,并在需要时replace/模拟它/等等。
使它成为一个单例实例可以简单地确保你不再需要分配更多types的对象(因为你只需要一个)。
其实我find了另一个没有提到的答案:静态方法很难testing。
看起来大多数testing框架对于模拟实例方法都很有效,但是其中许多testing框架没有以一种体面的方式处理静态方法的模拟。
在大多数编程语言中,类都避开了许多types系统。 虽然一个类,其静态方法和variables是一个对象,但它往往不能实现一个接口或扩展其他类。 因为这个原因,它不能以多态的方式使用,因为它不能是另一种types的子types。 例如,如果你有一个接口IFooable
,这是其他类的几个方法签名所要求的,那么类对象StaticFoo
不能用于IFooable
,而FooSingleton.getInstance()
可以(假设FooSingleton
实现IFooable
)。
请注意,正如我对Heinzi的回答评论的那样,一个单例是控制实例化的模式。 它使用Class.getInstance()
replacenew Class()
,它使Class
的作者更多地控制实例,他可以使用它来防止创build不需要的实例。 单身人士只是一个非常特殊的工厂模式,应该这样对待。 常见的使用使得它成为全球登记处的特殊情况,而这往往是最糟糕的,因为全球登记处不应该被无情地使用。
如果你打算提供全局帮助函数,那么静态方法就可以正常工作。 该类不会充当类,而只是作为一个名称空间。 我build议你保持高凝聚力,否则你可能会遇到最古怪的耦合问题。
格尔茨
back2dos
在使用哪一个之间有一个折衷。 单身人士可能有也可能没有国家,他们指的是对象。 如果他们不保持状态,只用于全局访问,那么静态会更好,因为这些方法会更快。 但是如果你想利用对象和OOP概念(inheritance多态),那么singleton就更好了。
考虑一个例子:java.lang.Runtime是java中的一个单例类。 这个类允许每个JVM有不同的实现。 每个JVM的实现是单个的。 如果这个类是静态的,我们不能通过基于JVM的不同实现。
我发现这个链接真的很有用: http : //javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?
希望能帮助到你!!
对于我“想要Object State使用Singleton,要function使用静态方法”
这取决于你想要的。 无论何时你想要对象状态(例如像Null状态而不是null
或默认状态那样的多态性),单例对你来说是合适的select,而静态方法在你需要函数时使用(接收input然后返回一个输出)。
我build议单例情况下,实例化后它应该始终是相同的状态。 它不应该是可克隆的,也不能接收任何值(除了文件中的静态configuration,例如java中的属性文件)。
PS这两者之间的performance在毫秒级上是不同的,所以首先关注架构 。
辛格尔顿不是无国籍的,它拥有全球性的国家。
我能想到的使用Singleton的一些原因是:
- 避免内存泄漏
- 为应用程序中的所有模块提供相同的状态,例如数据库连接