zoukankan      html  css  js  c++  java
  • 关于单例模式----这些你都知道吗?

    前言

      这篇是个人总结C#设计模式系列文章的第一篇,本系列文章将由浅入深的研究C#开发中常用到的各种设计模式。欢迎大家批评指正。

      本篇将从单例模式的基本概念开始,由浅入深探究C#中单例模式的几种不同的实现方法,并分析其中的区别和各自的适用范围(有点啰嗦,大侠请直接跳过前面)。

    基本概念

      单例模式属于创建型模式,其意图是保证一个类只有一个实例,并提供一个可以访问它的全局访问点。对于一些情况只有一个实例很重要,例如一个用户登陆了一个系统之后经常在不同模块之间点击,理论上所有模块应该共用同一个Login对象。而如何才能保证一个类只有一个实例并且很容易被访问呢?最简单的方法就是让类本身保存它的唯一实例,也就是单例模式。

    1、基本实现(惰性加载、懒汉模式)

     1 public sealed class Singleton 
     2     {
     3         public static Singleton singletonInstance;
     4         private Singleton() { }
     5         public static Singleton getSingletonInstance() 
     6         {
     7             if (singletonInstance == null)
     8             {
     9                     singletonInstance = new Singleton();
    10             }
    11             return singletonInstance;
    12         }
    13     }

      这种实现方式最常见,对于适用于单线程的小应用程序,通过懒加载避免了在应用程序启动时创建了不必要的实例。缺点也很明显,这种实现不是线程安全的,在多线程环境下有可能会得到多个类的实例(多个线程同时访问singletonInstance == null时)。

    2、双重锁定

    要想实现线程安全也很简单,使用lock即可(类似于java中的synchronized),代码如下:

     1     public sealed class Singleton 
     2     {
     3         public static Singleton singletonInstance;
     4         private static readonly object temp_lock = new object();
     5         private Singleton() { }
     6         public static Singleton getSingletonInstance() 
     7         {
     8             if (singletonInstance == null)
     9             {
    10                 lock (temp_lock)
    11                 {
    12                     if (singletonInstance == null)
    13                     {
    14                         singletonInstance = new Singleton();
    15                     }
    16                 }
    17             }
    18             return singletonInstance;
    19         }
    20     }

      lock关键字可以保证代码块被完整运行,不会被其他线程打断。temp_lock是一个进程辅助对象,线程在进入时先对辅助对象加锁然后再检测对象是否被创建,这样就可以确保只有一个实例被创建。在第10行处才加锁,可以减少一部分开销,不必每次都加锁。这种实现解决保证了线程安全,也实现了延迟加载,

    3、饿汉模式

      这种方式实现起来最简单,最常用,而且也是线程安全的, 由于构造函数是私有的,不会在类的外部被创建,而Singleton 实例被私有静态成员变量引用,所以在类的getSingletonInstance方法被首次调用之前,不会发生实例化。

        public sealed class Singleton 
        {
            private static Singleton singletonInstance = new Singleton();
            private Singleton() { }
            public static Singleton getSingletonInstance() 
            {
                return singletonInstance;
            }
        }

      这种方法的缺点就是不能在对象实例化之前做执行其他任务,类被加载时,CLR会自动实例化这个类,而不是在第一次调用GetInstance()后才实例化。

    4、内部类

        public sealed class Singleton
        {
            private Singleton() { }
            private static class SingletonHolder{
                internal static readonly Singleton singletonTnstance = new Singleton();
            }
            public static Singleton getSingletonInstance
            {
                get
                {
                    return SingletonHolder.singletonTnstance;
                }
            }
        }

      使用这种方法初始化工作由SingletonHolder的一个静态成员来实现,可以实现延迟初始化,尤其是当实例化instance很消耗资源时更具备优势,上述几种的其他优点这里也具备,是值得推荐的一种实现方式。

      由于C#中的enum类型不支持方法,所以不能像java中那样通过enum实现单例模式。

    总结:

      其实单例模式的只要思想在于“如何控制用户使用new对一个类的构造器的任意调用”。另外上述实现方法中没有考虑对象销毁的管理,当然对于.NET来说,这方面一般不需要我们来考虑。

      同时单例模式有以下个优点:

      1、保持对象状态一致,阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。

      2、可以作为对全局变量的一种改进方式,避免一些存储唯一实例的全局变量。

      3、内存开销,相对于创建多个实例,减少内存开销。

                                                                        (暂时整理这么多了,有其他问题再补充。)

  • 相关阅读:
    数据库课程设计心得【3】存储过程的运用
    看BBC研究大脑的科教片中“放松产生灵感”的笔记
    成功干掉“恶心的U盘自动运行病毒免疫目录”!共享方法,让更多的人干掉这东西!
    分享一大堆最新dot net asp.net c# 电子书下载 , 英文原版的。经典中的经典
    SQL学习之 对GROUP BY 和 HAVING 的理解 学习笔记
    关于Theme中.skin与css需要理清的关系
    最近的学习笔记,记录一些通俗易懂的学习类文章。更像是好资料参与索引。
    关于DNN Module开发学习以来的一点总结
    工具发布!QQ空间阅读与备份工具
    被忽视的大道理
  • 原文地址:https://www.cnblogs.com/Legolas/p/SingletonPattern.html
Copyright © 2011-2022 走看看