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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2765060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 12:36:15  来源:igfitidea点击:

Why use a singleton instead of static methods?

javadesign-patternssingleton

提问by Sebastien Lorber

I've never found good answers to these simple questions about helper/utility classes:

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

Why would I create a singleton (stateless) instead of using static methods?

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

Why would an object instance be needed if an object has no state?

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

采纳答案by Heinzi

Often, singletons are used to introduce some kind of global stateto an application. (More often than really necessary, to be honest, but that's a topic for another time.)

通常,单例用于向应用程序引入某种全局状态。(老实说,这通常比真正有必要,但这是另一个话题。)

However, there are a few corner cases where even a statelesssingleton can be useful:

但是,在某些极端情况下,即使是无状态单例也很有用:

  • You expect to extend it with state in the foreseeable future.
  • You need an object instancefor some particular technicalreason.
    Example: Synchonization objects for the C# lockor the Java synchronizedstatement.
  • You need inheritance, i.e., you want to be able to easily replace your singleton with another one using the same interface but a different implementation.
    Example: The Toolkit.getDefaultToolkit()method in Java will return a singleton whose exact type is system dependent.
  • You want reference equalityfor a sentinel value.
    Example: DBNull.Valuein C#.
  • 您希望在可预见的未来用 state 扩展它。
  • 由于某些特定的技术原因,您需要一个对象实例。示例:C#或 Java语句的同步对象。
    locksynchronized
  • 您需要继承,即,您希望能够使用相同的接口但不同的实现轻松地将您的单例替换为另一个单例。
    示例:Toolkit.getDefaultToolkit()Java 中的方法将返回一个单例,其确切类型取决于系统。
  • 你想要一个哨兵值的引用相等。示例:在 C# 中。
    DBNull.Value

回答by tzaman

I could see a case for a stateless singleton being used instead of a static methods class, namely for Dependency Injection.

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

If you have a helper class of utility functions that you're using directly, it creates a hidden dependency; you have no control over who can use it, or where. Injecting that same helper class via a stateless singleton instance lets you control where and how it's being used, and replace it / mock it / etc. when you need to.

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

Making it a singleton instance simply ensures that you're not allocating any more objects of the type than necessary (since you only ever need one).

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

回答by back2dos

In most programming languages classes elude a lot of the type system. While a class, with its static methods and variables is an object, it very often cannot implement an interface or extend other classes. For that reason, it cannot be used in a polymorphic manner, since it cannot be the subtype of another type. For example, if you have an interface IFooable, that is required by several method signatures of other classes, the class object StaticFoocannot be used in place of IFooable, whereas FooSingleton.getInstance()can (assuming, FooSingletonimplements IFooable).

在大多数编程语言中,类避开了很多类型系统。虽然具有静态方法和变量的类是一个对象,但它通常无法实现接口或扩展其他类。因此,它不能以多态方式使用,因为它不能是另一种类型的子类型。例如,如果您有一个 interface IFooable,它是其他类的多个方法签名所必需的,则该类对象StaticFoo不能代替IFooable,而FooSingleton.getInstance()可以(假设为FooSingletonimplements IFooable)。

Please note, that, as I commented on Heinzi's answer, a singleton is a pattern to control instantiation. It replaces new Class()with Class.getInstance(), which gives the author of Classmore control over instances, which he can use to prevent the creation of unneccessary instances. The singleton is just a very special case of the factory pattern and should be treated as such. Common use makes it rather the special case of global registries, which often ends up bad, because global registries should not be used just willy-nilly.

请注意,正如我对 Heinzi 的回答所评论的那样,单例是一种控制实例化的模式。它替换new Class()Class.getInstance(),这使作者Class可以对实例进行更多控制,他可以使用它来防止创建不必要的实例。单例只是工厂模式的一个非常特殊的情况,应该这样对待。普遍使用使它成为全局注册表的特殊情况,这通常最终会很糟糕,因为全局注册表不应该随意使用。

If you plan to provide global helper functions, then static methods will work just fine. The class will not act as class, but rather just as a namespace. I suggest, you preserve high cohesion, or you might end up with weirdest coupling issues.

如果您打算提供全局辅助函数,那么静态方法就可以正常工作。该类不会作为类,而只是作为一个命名空间。我建议你保持高内聚,否则你可能会遇到最奇怪的耦合问题。

greetz
back2dos

问候语
back2dos

回答by Indigo Praveen

Singleton is not stateless, it holds the global state.

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

Some reasons which I can think of using Singleton are:

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

  • To avoid memory leaks
  • To provide the same state for all modules in an application e.g database connection
  • 为了避免内存泄漏
  • 为应用程序中的所有模块提供相同的状态,例如数据库连接

回答by Sebastien Lorber

Actually i've found another answer not mentionned here: static methods are harder to test.

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

It seems most test frameworks work great for mocking instance methods but many of them no not handle in a decent way the mock of static methods.

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

回答by Atihska

There is a trade-off between using which one. Singletons may or may not have state and they refer to objects. If they are not keeping state and only used for global access, then static is better as these methods will be faster. But if you want to utilize objects and OOP concepts (Inheritance polymorphism), then singleton is better.

使用哪个之间需要权衡。单例可能有也可能没有状态,它们引用对象。如果它们不保持状态并且仅用于全局访问,那么静态更好,因为这些方法会更快。但是如果你想利用对象和 OOP 概念(继承多态),那么单例更好。

Consider an example: java.lang.Runtime is a singleton class in java. This class allows different implementations for each JVM. The implementation is single per JVM. If this class would have been static, we cannot pass different implementations based on JVM.

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

I found this link really helpful: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html?

我发现这个链接真的很有帮助:http: //javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

Hope it helps!!

希望能帮助到你!!

回答by Toomtarm Kung

For me "Want Object State use Singleton, Want Function use static method"

对我来说“想要对象状态使用单例,想要函数使用静态方法”

It depends on what you want. Whenever you want the object state (e.g. Polymorphism like Null state instead of null, or default state), singleton is the appropriate choice for you whereas the static method use when you need function (Receive inputs then return an output).

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

I recommend for the singleton case, it should be always the same state after it is instantiated. It should neither be clonable, nor receive any value to set into (except static configuration from the file e.g. propertiesfile in java).

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

P.S. The performance between these 2 are different in milliseconds, so focus on Architecturefirst.

PS 这2个之间的性能以毫秒为单位不同,所以先关注架构