C# 单例模式

2023-10-20 18:44:13 浏览数 (2)

单例模式

单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 主要解决:一个全局使用的类频繁地创建与销毁。 何时使用:当您想控制实例数目,节省系统资源的时候。 如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 关键代码:构造函数是私有的。

实现:懒汉式,线程不安全

该实现没有额外开销,不要求线程安全的情况下可以使用:

代码语言:javascript复制
public class ApplicationContext
{
    private static ApplicationContext instance = null;
    private ApplicationContext() { }

    public static ApplicationContext Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new ApplicationContext();
            }
            return instance;
        }
    }

    public string UserId { get; set; }
}

实现:懒汉式,线程安全

由于每次访问单例类实例都会加锁,而加锁是一个非常耗时的操作,故不推荐使用:

代码语言:javascript复制
public class ApplicationContext
{
    private readonly static object lockObj = new object();
    private static ApplicationContext instance = null;
    private ApplicationContext() { }

    public static ApplicationContext Instance
    {
        get
        {
            lock (lockObj)
            {
                if (instance == null)
                {
                    instance = new ApplicationContext();
                }
            }
            return instance;
        }
    }

    public string UserId { get; set; }
}

实现:懒汉式,双重校验锁

在前面的基础上进行改进,只在第一次创建实例时加锁,提高访问性能:

代码语言:javascript复制
public class ApplicationContext
{
    private readonly static object lockObj = new object();
    private static ApplicationContext instance = null;
    private ApplicationContext() { }

    public static ApplicationContext Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                    {
                        instance = new ApplicationContext();
                    }
                }
            }
            return instance;
        }
    }

    public string UserId { get; set; }
}

实现:饿汉式,线程安全

写法简单,线程安全,但构造时机不是由程序员掌控的:

代码语言:javascript复制
public class ApplicationContext
{
    private static ApplicationContext instance = new ApplicationContext();
    private ApplicationContext() { }

    public static ApplicationContext Instance
    {
        get
        {
            return instance;
        }
    }

    public string UserId { get; set; }
}

不仅如此,假如ApplicationContext中存在其他静态方法,我去调用的时候就会导致单例构造实例,无法做到访问单例时创建实例

当然,通过内部类实现,可以解决这个问题:

代码语言:javascript复制
public class ApplicationContext
{
    class Nested
    {
        internal static readonly ApplicationContext instance = new ApplicationContext();
    }

    private ApplicationContext() { }

    public static ApplicationContext Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    public string UserId { get; set; }
}

实现单例基类

代码语言:javascript复制
// 由于单例基类不能实例化,故设计为抽象类
public abstract class Singleton<T> where T : class
{
    // 这里采用实现5的方案,实际可采用上述任意一种方案
    class Nested
    {
        // 创建模板类实例,参数2设为true表示支持私有构造函数
        internal static readonly T instance = Activator.CreateInstance(typeof(T), true) as T;
    }
    private static T instance = null;
    public static T Instance { get { return Nested.instance; } }
}

参考资料

  • 《剑指offer》
  • http://www.runoob.com/design-pattern/singleton-pattern.html
  • https://blog.csdn.net/ycl295644/article/details/46770451

0 人点赞