单例模式

https://blog.csdn.net/suoxd123/article/details/103640967
https://www.cnblogs.com/xiaohanxixi/p/13197362.html

单例类实现机制

核心思路:构造函数私有化+在类内部做类自己的静态声明

两种实现方式

饿汉模式 懒汉模式,两种区别在于声明时是否要实例化

饿汉模式

在做静态声明时,将类实例化

// sealed保证该类不可以被继承
// 类在定义时就已经完成实例化了,没有达到延迟加载的效果,如果从来未使用过这个类会造成内存的浪费
public sealed class SingletonMode1()
{
    private static SingletonMode1 singletonMode1 = new SingletonMode1();
    private SingletonMode1(){}
    public static SingletonMode1 GetSingleton(){
        return singletonMode1;
    }
}

懒汉模式

为了加快程序加载,在做静态声明时,不做实例化,只有在调用时才实例化,

// 保证了延迟加载
// 但是如果多个线程访问GetSingleton()会实际产生多个实例
public class SingletonMode2()
{
    private static SingletonMode2 singletonMode2;
    private SingletonMode2(){}
    public static SingletonMode2 GetSingleton(){
        if(singletonMode2 == null){
            singletonMode2 = new SingletonMode2();
        }
        return singleton2;
    }
}

双重加锁机制★★

//保证了延迟加载
//保证了不会多个线程访问GetSingleton()
public class SingletonMode3()
{
    private static SingletonMode3 singletonMode3;
    private SingletonMode3(){}
    private static readonly object syncRoot = new object();
    public static SingletonMode3 GetSingleton(){
        //先判断是否已经实例化过,,如果实例化返回对象,如果没有实例化该线程加锁
        if(singletonMode3 == null){
            //多线程访问到这一步遇到锁,只能一个线程通过
            lock(syncRoot){
                //线程通过锁后,还需要再判断一下,是否对象已经实例化过
                //主要是为了防止,线程1,线程2同时通过了第一次判断,线程1先通过锁实例化了对象,然后线程2接着通过锁,如果此时不判断一下,会实例化多个对象
                if(singletonMode3 == null){
                    singletonMode3 = new SingletonMode3();
                }
            }
        }
        return singletonMode3;
    }
}

懒加载模式

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
           new Lazy<Singleton6>(()=> new Singleton());
    public static Singleton Instance { get { return lazy.Value; } }
    private Singleton() { }
}

总结

  • 延迟初始化:单例类在第一次被请求时进行实例化,而不是程序启动时立即创建。
  • 实例化控制:通过私有化构造函数和静态方法来控制实例化过程,确保只有一个实例存在。
  • 状态保持:因为单例模式只有一个实例,所以可以在多处使用相同的状态信息。
  • 类是密封的:尽管这不是强制的,一般不推荐继承还有静态成员的类(父类的静态成员属于父类本身,虽然可以通过子类的类名来访问,但无法被override,父类的静态成员在子类中是公用的)

单例类的应用场景

单例模式允许类只有一个实例,并提供全局访问点。它通常在需要确保只有一个对象存在的情况下使用,例如日志系统、数据库连接、设备通讯类等。

单例类和静态类的辨析

静态类(Static Class)
静态类是一种只包含静态成员的类,它们不能被实例化。所有成员都是静态的,可以通过类名直接访问,不需要创建对象。
工具性质:静态类通常用于存储公共的、通用的方法或变量,例如常量、扩展方法等。
无法实例化:因为静态类不能被实例化,所以无法创建它们的实例。它们只能通过类名来访问其成员。

相同点

  1. 单例模式和静态类均无法在外部实例化
  2. 类只有一个实例,提供全局的访问点

主要区别:

  1. 实例化:单例类可以实例化,但只允许一个实例存在,而静态类无法实例化。
  2. 状态和数据存储:单例类可以保存状态和数据,因为它们是可以实例化的对象,而静态类主要用于存储静态成员,不保持状态。
  3. 灵活性:单例类在设计上更加灵活,可以支持接口实现、延迟初始化等,而静态类是静态的、不能继承或实现接口的

单例字典模式

在实际的应用中,类往往不会直接设计成单例模式,会将一个集合性质的类设计成单例,通过这个类来间接实现单例

   public class Singletons
    {
        private static Lazy<Dictionary<string, Singleton>> SingletonDic = new Lazy<Dictionary<string, Singleton>>();
        // 公共访问点,用于获取单例对象
        public static Singleton GetInstance(string key = null)
        {
            if (key == null)
            {
                return SingletonDic.Value.FirstOrDefault().Value;
            }
            else
            {
                if (SingletonDic.Value.ContainsKey(key))
                {
                    return SingletonDic.Value[key];
                }
            }
            return null;
        }
        public static void AddInstance(string key)
        {
            SingletonDic.Value.Add(key,new Singleton());
        }
        public static void DeleteInstance(string key)
        {
            if (SingletonDic.Value.ContainsKey(key))
                SingletonDic.Value.Remove(key);
        }
        private Singletons(){ }
        public sealed class Singleton{ }
    }
posted @ 2023-02-13 09:36  回首起了风沙  Views(2)  Comments(0Edit  收藏  举报