使用场景

需要频繁实例化然后销毁的对象

  • 首页页面缓存

    创建对象时耗时过多或者耗资源过多

  • 比如 I/O 与数据库的连接等。

  • Web中的配置对象
  • 数据库的连接池

    工具类对象

  • 要求生产唯一序列号

  • WEB中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来

    优缺点

  1. 省:在内存中只有一个对象,节省内存空间。
  2. 快:避免频繁的创建销毁对象,可以提高性能。
  3. 避免对共享资源的多重占用。
  4. 可以全局访问。

    设计原理

    Q:确保实例的唯一性
    A:私有化构造器,保护对象的创建

    实现步骤

  • 私有化构造器,保护对象的创建
  • 在类内部创建一个私有化对象(实例)
  • 创建一个公共方法返回这个实例,因为无法创建对象,所以这个方法一定是 static 的,所以改方法返回的实例也是static 的。

    代码实现

    懒加载式

    单例实例被延迟加载,即只有在真正使用的时候才会实例化一个对象并交给自己的引用。

    完美实现

    1. /// <summary>
    2. /// Double-check locking
    3. /// </summary>
    4. public class Singleton2
    5. {
    6. private static Singleton2 instance = null;
    7. /// <summary>
    8. /// 通常用来加锁的字段是私有的
    9. /// </summary>
    10. private static object obj = new object();
    11. /// <summary>
    12. /// 单例模式私有化构造器
    13. /// </summary>
    14. private Singleton2() { }
    15. public static Singleton2 Instance
    16. {
    17. get
    18. {
    19. //首次检查用来提示性能,因为加锁比较耗时
    20. if (instance == null)
    21. {
    22. lock (obj)
    23. {
    24. if (instance == null)
    25. {
    26. instance = new Singleton2();
    27. }
    28. }
    29. }
    30. return instance;
    31. }
    32. }
    33. }

    内存饱满式

    优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
    缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

    完美实现

    1. /// <summary>
    2. /// 借助Lazy特性的静态构造法
    3. /// </summary>
    4. public sealed class Singleton1
    5. {
    6. private static readonly Lazy<Singleton1> lazy = new Lazy<Singleton1>(() => new Singleton1());
    7. public static Singleton1 Instance { get { return lazy.Value; } }
    8. /// <summary>
    9. /// 单例模式私有化构造器
    10. /// </summary>
    11. private Singleton1() { }
    12. public void Demo()
    13. {
    14. Console.WriteLine("Demo");
    15. }
    16. }

    参考文档

    https://www.cnblogs.com/zhaoshujie/p/14323654.html 单例模式的六种实现