单例模式
概述
保证一个类仅有一个实例,并提供一个访问它的全局访问点
懒汉式模式
该模式的特点是类加载时没有生成单例
饿汉式模式
该模式的特点是类一旦加载就创建一个单例
结构图
代码实现
饿汉单例
单例类
/// <summary> /// 饿汉模式 /// </summary> public class Singleton1 { private static readonly Singleton1 instance = new Singleton1(); private Singleton1() { Console.WriteLine("创建了Singleton1实例"); } public static Singleton1 GetInstance() { return instance; } }
客户端
class Program { static void Main(string[] args) { Singleton1 s1 = Singleton1.GetInstance(); Singleton1 s2 = Singleton1.GetInstance(); if (s1 == s2) { Console.WriteLine("两个是同一个对象"); } Console.Read(); } }
运行结果
懒汉模式加锁加双重检测
单例类
/// <summary> ///懒汉模式加锁加双重检验 /// </summary> public class Singleton2 { private static Singleton2 instance; private static readonly object syncRoot = new object(); private Singleton2() { Console.WriteLine("创建了Singleton2实例"); } public static Singleton2 GetInstance() { if (instance == null) { lock (syncRoot) { if (instance == null) { instance = new Singleton2(); } } } return instance; } }
客户端
class Program { static void Main(string[] args) { Singleton2 s1 = Singleton2.GetInstance(); Singleton2 s2 = Singleton2.GetInstance(); if (s1 == s2) { Console.WriteLine("两个是同一个对象"); } Console.Read(); } }
运行结果
静态内部类
单例类
/// <summary> /// 静态内部类懒汉模式同时线程安全 /// </summary> public class Singleton3 { private static class SingletonHolder { public static readonly Singleton3 instance = new Singleton3(); } private Singleton3() { Console.WriteLine("创建了Singleton3实例"); } public static Singleton3 GetInstance() { return SingletonHolder.instance; } }
客户端
class Program { static void Main(string[] args) { Singleton3 s1 = Singleton3.GetInstance(); Singleton3 s2 = Singleton3.GetInstance(); if (s1 == s2) { Console.WriteLine("两个是同一个对象"); } Console.Read(); } }
运行结果
多利模式
多利类
/// <summary> /// 静态内部类懒汉模式同时线程安全 /// </summary> public class Singleton4 { private static class SingletonHolder { public static readonly Dictionary<string, Singleton4> instances = new Dictionary<string, Singleton4>() { ["key1"] = new Singleton4(), ["key2"] = new Singleton4(), ["key3"] = new Singleton4(), }; } private Singleton4() { Console.WriteLine("创建了Singleton4实例"); } public static Singleton4 GetInstance(string key) { return SingletonHolder.instances.TryGetValue(key, out _) ? SingletonHolder.instances[key] : null; } }
客户端
class Program { static void Main(string[] args) { Singleton4 s1 = Singleton4.GetInstance("key1"); Singleton4 s2 = Singleton4.GetInstance("key1"); if (s1 == s2) { Console.WriteLine("两个是同一个对象"); } Console.Read(); } }
运行结果
优势
单例模式可以保证内存里只有一个实例,减少了内存的开销。
可以避免对资源的多重占用。
单例模式设置全局访问点,可以优化和共享资源的访问。
使用场景
一个全局使用的类频繁地创建与销毁。
要求全局只生产一个
创建的一个对象需要消耗的资源过多。
单例模式还可以在集群、进程间来保证单例
缺陷
单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。