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

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


当前回答

与静态类相比,Singleton模式有几个优点。首先,单例可以扩展类和实现接口,而静态类不能(它可以扩展类,但不继承它们的实例成员)。单例可以延迟或异步初始化,而静态类通常在首次加载时初始化,这会导致潜在的类加载器问题。然而,最重要的优点是,可以在不强迫用户假设只有一个实例的情况下以多态的方式处理单态。

其他回答

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

单个对象存储在堆中,但静态对象存储在堆栈中。我们可以克隆(如果设计器不允许)单例对象,但不能克隆静态类对象.单类遵循OOP(面向对象原则),静态类则不遵循。我们可以用Singleton类实现接口,但类的静态方法(例如C#静态类)不能。

静态类示例

public class Any {

    private static Any instance = new Any();

    private Singleton() {
        System.out.println("creating");
    }
}

单例模式只存在一个实例:

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
        System.out.println("creating");
        if (instance != null) {
            throw new RuntimeException("Imposible create a new instance ");
        }
    }
}

下面是静态类和单例之间的一些主要区别:

1.Singleton是一种模式,而不是像static那样的关键字。因此,对于创建静态类,静态关键字就足够了,而对于单例,则需要为单例编写逻辑。

2.单例类必须具有私有的默认实例构造函数,而静态类不能包含任何实例构造函数。

3.静态类既不实例化也不扩展,而单例类可以实例化。

4.静态类是隐式密封的,但单例类必须修饰为显式密封的。

5.单例可以实现接口或从另一个类继承,但静态类既不实现接口,也不从任何其他类扩展。

6.我们不能用静态类实现依赖注入,但单例类可以实现DI,因为它可以是接口驱动的。静态类的作用域位于应用程序域级别,因为它由CLR管理,而单例对象的作用域则跨越应用程序生命周期。

7.静态类不能有任何析构函数,但单例类可以定义析构函数。

8.单例类实例可以作为参数传递给另一个方法,而静态类不能传递,因为它只包含静态成员。

为了说明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();
    }
}