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

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

  • 为什么我要创建一个单例(无状态)而不是使用静态方法?
  • 如果对象没有状态,为什么需要对象实例?
48172 次浏览

Often, singletons are used to introduce some kind of global state to 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 stateless singleton can be useful:

  • You expect to extend it with state in the foreseeable future.
  • You need an object instance for some particular technical reason.
    Example: Synchonization objects for the C# lock or the Java synchronized statement.
  • 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 equality for a sentinel value.
    Example: DBNull.Value in C#.

I could see a case for a stateless singleton being used instead of a static methods class, namely for 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).

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 StaticFoo cannot be used in place of IFooable, whereas FooSingleton.getInstance() can (assuming, FooSingleton implements 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 Class more 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.

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

Singleton is not stateless, it holds the global state.

Some reasons which I can think of using Singleton are:

  • To avoid memory leaks
  • To provide the same state for all modules in an application e.g database connection

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.

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.

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.

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

Hope it helps!!

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).

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. properties file in java).

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

According to GoF’s book Design Patterns, chapter ‘Singleton’, class operations have the following drawbacks compared to singletons (bold emphasis mine):

  1. More flexible than class operations. Another way to package singleton’s functionality is to use class operations (that is, static member functions in C++ or class methods in Smalltalk). But both of these language techniques make it hard to change a design to allow more than one instance of a class. Moreover, static member functions in C++ are never virtual, so subclasses can’t override them polymorphically.