静态类和单例模式之间存在什么实际的区别?

两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?


当前回答

Singleton的一个主要优势:多态性例如:使用Class工厂创建实例(比如基于某些配置),我们希望这个对象是真正的单实例。

其他回答

这是一篇好文章:http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

静态类

具有所有静态方法的类。更好的性能(静态方法在编译时绑定)无法重写方法,但可以使用方法隐藏。(Java中隐藏的方法是什么?甚至JavaDoc的解释都令人困惑)公共级动物{公共静态void foo(){System.out.println(“动物”);}}公共课猫延伸动物{public static void foo(){//隐藏Animal.foo()System.out.println(“类别”);}}

辛格尔顿

只能实例化一次的对象。方法可以被重写(为什么Java不允许重写静态方法?)比静态方法更容易模拟更善于保持状态

总之,我只使用静态类来保存util方法,而使用Singleton来处理其他所有事情。


编辑

静态类也被延迟加载。谢谢@jmoreno(静态类初始化何时发生?)静态类的方法隐藏。谢谢@MaxPeng。

在许多情况下,这两者没有实际差异,特别是如果单例实例从未更改或更改非常缓慢,例如保持配置。

我想说,最大的区别是单例仍然是一个普通的JavaBean,而不是专门的仅静态Java类。正因为如此,单身汉在很多情况下都被接受;它实际上是默认的Spring框架的实例化策略。消费者可能知道也可能不知道它是一个被传递的单例,它只是把它当作一个普通的Javabean。如果需求发生变化,而单例需要成为原型,正如我们在Spring中经常看到的那样,它可以完全无缝地完成,而无需对消费者进行一行代码更改。

前面有人提到,静态类应该是纯过程的,例如java.lang.Math。在我看来,这样的类永远不应该被传递,它们永远不应该将静态final以外的任何属性作为属性。对于其他一切,使用单例,因为它更灵活,更易于维护。

a.序列化-静态成员属于类,因此无法序列化。

虽然我们已经将构造函数私有化,但静态成员变量仍将被携带到子类中。

c.我们不能进行延迟初始化,因为只有在类加载时才会加载所有内容。

主要区别在于:

Singleton有一个实例/对象,而静态类是一堆静态方法Singleton可以在静态时通过接口进行扩展班级不可能。Singleton可以继承,它支持另一方面,静态类不能继承SOLID原则我们需要自己做出改变。Singleton对象可以传递给方法,而静态类作为它没有实例不能作为参数传递

为了说明Jon的观点,如果Logger是一个静态类,下面所示的操作是无法完成的。类SomeClass希望ILogger实现的一个实例传递到其构造函数中。

Singleton类对于实现依赖注入非常重要。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}