董昊(昊子)的专栏

一个系统构架师、系统分析师(努力学习中...)

用户操作
[即时聊天] [发私信] [加为好友]
董昊ID:edisundong
275751次访问,排名215好友10人,关注者56
做最好的自己
edisundong的文章
原创 129 篇
翻译 0 篇
转载 16 篇
评论 273 篇
董昊的公告
 程序人生:

 21岁通过<高级程序员>考试。

 23岁大学毕业,在一家著名手机企业。

 24岁通过<系统分析师>考试。

 开发语言:
 .net从asp+用到.net 3.5
 java业余爱好者

 研究方向:
 目前的研究方向是企业级web开发编译器

 我的联系方式:
 edisundong_163.com
 (_替换成@)

最近评论
dskra:"3:如何加强公司的管理"
过去就觉得公司现在越来越遭,现在觉得就是第3条的原因啊。
dskra:我们公司现在就出现"3:如何加强公司的管理。"的现象了,过去一直找不出原因,现在明白了。
dskra:我们公司现在就出现"3:如何加强公司的管理。"的现象了,过去一直找不出原因,现在明白了。
thesameway:51旧书网 同城易书
www.51jiushu.com
www.51jiushu.net
二手书、旧书同城交易平台
分类齐全、快速发布、准确搜索
msnadair:人要奋进,要敢于发表,善于发表自己的看法观点
文章分类
收藏
    相册
    java
    俱乐部
    宁波.net俱乐部
    宁波.NET俱乐部
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 单件模式(Singleton Pattern)收藏

    新一篇: 中小型软件开发项目管理 | 旧一篇: 肖波:《何经华先生,我要对您说“不”》之后的事

    概述

    Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。那么绕过常规的构造器(new),提供一种机制来保证一个类只有一个实例就是单件模式了。客户程序员在调用这个类时,是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。

    意图

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    模型图

    逻辑模型图: 

    物理模型图:

    生活中的例子

    微软的CEOSingleton微软只有一个CEO,所以无论他的身份为何,他都有一个全局的访问点---微软的CEO”。

    五种实现

    1.简单实现

     

     

     public sealed class Singleton
     
    {
          static Singleton instance=null
    ;
          Singleton()
          
    {
        
      }
       public static
     Singleton Instance
         
    {
         get

          {
             if (instance==null
    )
             
    {
              instance = new
     Singleton();
           
      }
              return
     instance;
      
      }
     
     }
    }

    这种方式的实现的“CEO”并不是线程安全的,也就是在多线程的情况下他是有可能产生两个“CEO”的。如代码所写,如果同时有两个线程去判断(instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的原则。

     

     

    2.安全的线程

     public sealed class Singleton
      {
       
    static Singleton instance=null;
      
    static readonly object padlock = new object();

     Singleton()
     
    {
      }

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


     

    这种方式的实现对于线程来说是安全的。我们首先创建了一个进程辅助对象,线程在进入时先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建,因为在同一个时刻加了锁的那部分程序只有一个线程可以进入。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(instence == null)为假,不会再去创建对象实例了。但是这种实现方式增加了额外的开销,损失了性能。

    3.双重锁定

     1 public sealed class Singleton
     2 {
     3     static Singleton instance=null;
     4     static readonly object padlock = new object();
     5
     6     Singleton()
     7      {
     8     }
     9
    10     public static Singleton Instance
    11      {
    12         get
    13          {
    14             if (instance==null)
    15              {
    16                 lock (padlock)
    17                  {
    18                     if (instance==null)
    19                      {
    20                         instance = new Singleton();
    21                     }
    22                 }
    23             }
    24             return instance;
    25         }
    26     }
    27 }
    28

    这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建时它才加锁,有了我们上面第一部分的里面的分析,我们知道,加锁后还得再进行对象是否已被创建的判断。它解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。它还允许您将实例化延迟到第一次访问对象时发生。实际上,应用程序很少需要这种类型的实现。大多数情况下我们会用静态初始化。这种方式仍然有很多缺点:无法实现延迟初始化。

    4.静态初始化

     1 public sealed class Singleton
     2 {
     3     static readonly Singleton instance=new Singleton();
     4
     5     static Singleton()
     6      {
     7     }
     8
     9     Singleton()
    10      {
    11     }
    12
    13     public static Singleton Instance
    14      {
    15         get
    16          {
    17             return instance;
    18         }
    19     }
    20 }
    21

    看到上面这段富有戏剧性的代码,我们可能会产生怀疑,这还是Singleton模式吗?在此实现中,将在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化。该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。

    该实现与前面的示例类似,不同之处在于它依赖公共语言运行库来初始化变量。它仍然可以用来解决 Singleton 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。

    由于 Singleton 实例被私有静态成员变量引用,因此在类首次被对 Instance 属性的调用所引用之前,不会发生实例化。

    这种方法唯一的潜在缺点是,您对实例化机制的控制权较少。在 Design Patterns 形式中,您能够在实例化之前使用非默认的构造函数或执行其他任务。由于在此解决方案中由 .NET Framework 负责执行初始化,因此您没有这些选项。在大多数情况下,静态初始化是在 .NET 中实现 Singleton 的首选方法。

    5.延迟初始化

     1 public sealed class Singleton
     2 {
     3     Singleton()
     4      {
     5     }
     6
     7     public static Singleton Instance
     8      {
     9         get
    10          {
    11             return Nested.instance;
    12         }
    13     }
    14     
    15     class Nested
    16      {
    17         static Nested()
    18          {
    19         }
    20
    21         internal static readonly Singleton instance = new Singleton();
    22     }
    23 }
    24

    这里,初始化工作有Nested类的一个静态成员来完成,这样就实现了延迟初始化,并具有很多的优势,是值得推荐的一种实现方式。

    实现要点

    l        Singleton模式是限制而不是改进类的创建。

    l         Singleton类中的实例构造器可以设置为Protected以允许子类派生。

    l         Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。

    l         Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。

    l         Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。

    l         理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。