单件模式(Singleton Pattern)(综合讲解)

来源:互联网 发布:国产服装品牌 知乎 编辑:程序博客网 时间:2024/05/16 15:22

单件模式(Singleton Pattern

——.NET设计模式系列之二

Terrylee20051207

概述

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

从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责!

意图

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

模型图

逻辑模型图:

物理模型图:

生活中的例子

美国总统的职位是Singleton,美国宪法规定了总统的选举,任期以及继任的顺序。这样,在任何时刻只能由一个现任的总统。无论现任总统的身份为何,其头衔"美利坚合众国总统"是访问这个职位的人的一个全局的访问点。

五种实现

1.简单实现

 

 

 

 

该实现方式主要有两个优点:

l         由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化),即使它可能引入不想要的依赖性。

l         直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton

2.安全的线程

 

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

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

 1public 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

 

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

1public 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 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。

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

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

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

 1public 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

 

实现要点

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

 

 

l         可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的

优点

l         实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例

l         灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

缺点

l         开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。

l          可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

l         对象的生存期:Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除 对象实例,但这样会导致 Singleton 类中出现悬浮引用。

适用性

l         当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

l         当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

应用场景

l         每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。 (摘自吕震宇的C#设计模式(7)-Singleton Pattern

l         PC机中可能有几个串口,但只能有一个COM1口的实例。

l         系统中只能有一个窗口管理器。

l         .NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。

完整示例

这是一个简单的计数器例子,四个线程同时进行计数。

 

 

 

总结

Singleton设计模式是一个非常有用的机制,可用于在面向对象的应用程序中提供单个访问点。文中通过五种实现方式的比较和一个完整的示例,完成了对Singleton模式的一个总结和探索。用一句广告词来概括Singleton模式就是“简约而不简单”。

 

_________________________________________________________________________________________________ 源码下载:/Files/Terrylee/SigletonPattern.rar

参考文献:

C#计模式》,中国电力出版社

使用 Microsoft .NET 的企业解决方案模式

Implementing the Singleton Pattern in C#

MSDNExploring the Singleton Design Pattern

吕震宇C#设计模式(7)-Singleton Pattern

C#的Singleton设计模式

作者:TerryLee 出处:http://terrylee.cnblogs.com
Tag标签: Design Patterns,设计模式

 

 1using System;  

2using System.Threading;  

3  

4namespace SigletonPattern.SigletonCounter  

5 

6    /// <summary>  

7    /// 功能:简单计数器的单件模式  

8    /// 编写:Terrylee  

9    /// 日期:2005年12月06日

10    /// </summary>

11    public class CountSigleton

12    {

13        ///存储唯一的实例

14        static CountSigleton uniCounter = new CountSigleton();  

15   

16        ///存储计数值

17        private int totNum = 0;  

18   

19        private CountSigleton() 

20   

21        

22            ///线程延迟2000毫秒

23            Thread.Sleep(2000);

24        } 

25   

26        static public CountSigleton Instance() 

27   

28        

29   

30            return uniCounter; 

31   

32        } 

33        

34        ///计数加1

35        public void Add()

36        

37            totNum ++;

38        }  

39        

40        ///获得当前计数值

41        public int GetCounter()

42        

43            return totNum;

44        } 

45

46    }

47}

48

 

 1using System;  

2using System.Threading;  

3using System.Text;  

4  

5namespace SigletonPattern.SigletonCounter  

6 

7    /// <summary>  

8    /// 功能:创建一个多线程计数的类  

9    /// 编写:Terrylee

10    /// 日期:2005年12月06日

11    /// </summary>

12    public class CountMutilThread

13    {

14        public CountMutilThread()

15        {

16            

17        }

18

19        /// <summary>

20        /// 线程工作

21        /// </summary>

22        public static void DoSomeWork()

23        {

24            ///构造显示字符串

25            string results = "";

26

27            ///创建一个Sigleton实例

28            CountSigleton MyCounter = CountSigleton.Instance();

29

30            ///循环调用四次

31            for(int i=1;i<5;i++)

32            {

33                ///开始计数

34                MyCounter.Add();

35                

36                results +="线程";

37                results += Thread.CurrentThread.Name.ToString() + "——〉";

38                results += "当前的计数:";

39                results += MyCounter.GetCounter().ToString();

40                results += "/n";

41

42                Console.WriteLine(results);

43                

44                ///清空显示字符串

45                results = "";

46            }

47        }

48

49        public void StartMain()

50        {

51

52            Thread thread0 = Thread.CurrentThread; 

53   

54            thread0.Name = "Thread 0"

55   

56            Thread thread1 =new Thread(new ThreadStart(DoSomeWork)); 

57   

58            thread1.Name = "Thread 1"

59   

60            Thread thread2 =new Thread(new ThreadStart(DoSomeWork)); 

61   

62            thread2.Name = "Thread 2"

63   

64            Thread thread3 =new Thread(new ThreadStart(DoSomeWork)); 

65   

66            thread3.Name = "Thread 3"

67   

68            thread1.Start(); 

69   

70            thread2.Start(); 

71   

72            thread3.Start(); 

73            

74            ///线程0也只执行和其他线程相同的工作

75            DoSomeWork(); 

76        }

77    }

78}

79

 

 1using System;  

2using System.Text; 

3using System.Threading;  

4  

5namespace SigletonPattern.SigletonCounter  

6 

7    /// <summary>  

8    /// 功能:实现多线程计数器的客户端  

9    /// 编写:Terrylee

10    /// 日期:2005年12月06日

11    /// </summary>

12    public class CountClient

13    {

14        public static void Main(string[] args)

15        {

16       CountMutilThread cmt = new CountMutilThread();

17

18            cmt.StartMain();

19

20            Console.ReadLine();

21        }

22    }

23}

24

 

 

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

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

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

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

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

 

 1public 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            lock (padlock)

15            {

16                if (instance==null)

17                {

18                    instance = new Singleton();

19                }

20                return instance;

21            }

22        }

23    }

24}

25

26

 

 

 1public sealed class Singleton  

2 

3    static Singleton instance=null 

4  

5    Singleton()  

6     

7    }  

8  

9    public static Singleton Instance

10    {

11        get

12        {

13            if (instance==null)

14            {

15                instance = new Singleton();

16            }

17            return instance;

18        }

19    }

20}

这种方式的实现对于线程来说并不是安全的,因为在多线程的环境下有可能得到Singleton类的多个实例。如果同时有两个线程去判断(instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的原则。实际上在上述代码中,有可能在计算出表达式的值之前,对象实例已经被创建,但是内存模型并不能保证对象实例在第二个线程创建之前被发现。

 

 

posted on 2005-12-09 09:31 TerryLee 阅读(40407) 评论(100)  编辑 收藏 所属分类: Design Patterns

评论

 

写的非常好,本人最近准备在公司内部进行有关设计模式的培训,本文对我非常有帮助,我主要在看两本书:设计模式,以及C#设计模式。 谢谢!   

@KingWorld 我也学习设计模式不久 大家互相帮助^_^   回复  引用  查看    

#3楼  2005-12-15 09:38 neilzhang      

运行计数实例,显示的结果不对,线程2又重新技术了,请检查你的代码。   回复  引用  查看    

#4楼 [楼主] 2005-12-15 11:53 Terrylee      

上面的代码中有一处错误: results += i.ToString() + "——〉"; 应该为: results += Thread.CurrentThread.Name.ToString() + "——〉" 已修改 感谢neilzhang发现了问题!   回复  引用  查看    

#5楼  2005-12-17 17:04 泽来      

真不错   回复  引用  查看    

#6楼  2006-01-12 10:27 SWZ [未注册用户]

请问一下,totNum 及 ADD方法使用STATIC, 和单件的区别在哪?谢谢!   回复  引用  查看    

#7楼  2006-02-20 10:03 johnsir      

很受用,谢谢!!   回复  引用  查看    

#8楼  2006-02-20 11:52 A.Z      

不错哦   回复  引用  查看    

#9楼  2006-02-20 11:58 A.Z      

文中的Sigleton拼写是否有问题?   回复  引用  查看    

#10楼 [楼主] 2006-02-20 12:27 Terrylee      

 

@A.Z 确实有错误,谢谢!低级错误
  回复  引用  查看    

 

#11楼  2006-02-23 23:55 windwolf      

对文中最后一种实现————延迟初始化————的机制不是很理解,能解释下吗?   回复  引用  查看    

#12楼  2006-03-03 11:51 空空无量 [未注册用户]

# re: 探索设计模式(二):单件模式(Singleton Pattern) 回复 2006-02-23 23:55 by windwolf 对文中最后一种实现————延迟初始化————的机制不是很理解,能解释下吗? 我也有此疑问,延迟初始化的好处在什么地方?谢谢   回复  引用  查看    

#13楼  2006-04-14 22:08 NullPointer [未注册用户]

看的不大明白,能否帮忙解释下: 第二、三种实现为什么不直接锁instance,而要另外创建padlock? 另外,在你引用的参考文献《Implementing the Singleton Pattern in C#》 中,已在第三种实现前面标明了:// Bad code! Do not use!   回复  引用  查看    

#14楼  2006-04-14 22:22 happyhippy [未注册用户]

@ windwolf 对文中最后一种实现————延迟初始化————的机制不是很理解,能解释下吗? 贴一篇文章,讲静态初始化: http://msdn.microsoft.com/msdnmag/issues/05/01/StaticsinNET/default.aspx   回复  引用  查看    

#15楼  2006-04-14 23:40 happyhippy [未注册用户]

补充一种:在应用程序域加载时初始化 public class Singleton1 { public readonly static Singleton1 singleton = new Singleton1(); private Singleton1(){} } 当确定我们的应用程序在运行时,一定会使用Singleton实例,且创建该实例的开销不会很大,可以用此方法   回复  引用  查看    

#16楼 [楼主] 2006-04-17 08:30 Terrylee      

@NullPointer 加锁时还不知道instance实例是否为空,怎么对它加锁呢?引入padlock是一种线程辅助锁,仅仅是为了加锁而存在,不再参与其他任何事情。 至于第三种情况,在一定程度上造成了性能上的损失,但是他在某些情况下还是比较有用的,只是不推荐使用而已。可以看看Enterprise Library代码中有很多地方都用到了第三种情况来实现。   回复  引用  查看    

#17楼  2006-05-26 16:52 jedliu [未注册用户]

有个问题,如果我想我的Singleton只能创建三个而不是一个。我怎么做? 用数组?   回复  引用  查看    

#18楼  2006-06-09 13:05 蛙蛙池塘      

1.理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。 2.可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。 3.对象的生存期:Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除 对象实例,但这样会导致 Singleton 类中出现悬浮引用。 4.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 这四点没太明白   回复  引用  查看    

#19楼  2006-08-01 12:27 roydux      

上面的概述写的好差劲. 不是为了保证类只能有一个实例而用Singleton, 而是为了用Singleton而去保证类只能有一个实例. 目的都不明确. 下面的这段,写的就是废话了, "因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责! " 既然是对象,肯定集中了类的所有功能,如果它不能用这种功能的话,那它还叫实例么?晕 怎么写的,不会是图字数吧 这些东西完全可以不写嘛,写错就更糟糕了   回复  引用  查看    

#20楼  2006-08-01 12:29 roydux      

@jedliu singleton的特点就在于single上,如果你创建了3个,那跟singleton已经没什么关系了,而是多例模式了   回复  引用  查看    

#21楼 [楼主] 2006-08-01 12:42 TerryLee      

@roydux 1.这位朋友恕我直言,我没得罪你吧?说话不要那么火药味十足,先说明一下,我很鄙视你这种态度! 2.我不想跟你这种人解释什么,你明白一点就可以了:不是为了用模式而使用它,不知道是你的目的不明确还是我的不明确?照你的解释就是每一个模式我们都是特意使用这种模式去解决某类问题,而不是遇到某类问题时去使用某个模式! 3.如果你觉得废话的话,你大可不来这里,这里不欢迎像你这样的“高手”!   回复  引用  查看    

#22楼  2006-08-02 12:19 microshot [未注册用户]

@TerryLee 没太弄明白如何保证一个类不能使用new再实例化呢?   回复  引用  查看    

#23楼  2006-08-10 14:27 overred      

TerryLee 大哥应该再增加个泛型实现单件哦 呵呵   回复  引用  查看    

#24楼 [楼主] 2006-08-10 15:19 TerryLee      

@overred 嗯,后面有时间增加上,最近忙着看Atlas去了,设计模式好久没有更新了:-)   回复  引用  查看    

#25楼  2006-08-25 10:53 reader [未注册用户]

好象有点问题,创建单态的时候考虑了线程安全,访问的时候就不用考虑么?   回复  引用  查看    

#26楼  2006-08-27 11:28 Gorster      

文章不错,对我很受益,谢谢! 提醒一下,很多地方的Singleton都变成了Sigleton,最好能改一下   回复  引用  查看    

#27楼 [楼主] 2006-08-28 08:32 TerryLee      

@reader 是这样的   回复  引用  查看    

#28楼 [楼主] 2006-08-28 08:32 TerryLee      

@Gorster 谢谢提醒,上次没改过来,呵呵   回复  引用  查看    

#29楼  2006-08-31 20:41 cy[匿名] [未注册用户]

不错,学起来   回复  引用  查看    

#30楼 [楼主] 2006-09-01 08:39 TerryLee      

@cy[匿名] 谢谢!   回复  引用  查看    

#31楼  2006-09-06 11:50 DearSoul [未注册用户]

第四种方法,定义一个静态的构造函数,意图为何?   回复  引用  查看    

#32楼  2006-09-08 16:08 yanyan [未注册用户]

支持你,给我学习带来很大帮助。   回复  引用  查看    

#33楼  2006-09-22 08:53 壮志      

好文章   回复  引用  查看    

#34楼  2006-10-26 09:17 ZeroCool      

我的单件模式写法: private static Singleton _instance = null; public static Singleton Instance {     get { return (_instance == null) ? (_instance = new Singleton()) : _instance; } } 有点儿“孔已己”了,呵呵!   回复  引用  查看    

#35楼 [楼主] 2006-10-26 22:00 TerryLee      

@ZeroCool 只不过是写法的问题,我更倾向于用if语句,为了代码可读性:)   回复  引用  查看    

#36楼  2006-10-27 11:28 zhaosichao [未注册用户]

Good   回复  引用  查看    

#37楼 [楼主] 2006-10-27 17:51 TerryLee      

@zhaosichao :)   回复  引用  查看    

#38楼  2006-10-30 08:03 ZeroCool      

@TerryLee 我个人认为,如果用方法的话,GetInstance()会更具可读性,而对于这样简单的判断,我感觉使用Property更符合.NET的设计规范,:)   回复  引用  查看    

#39楼 [楼主] 2006-10-30 08:30 TerryLee      

@ZeroCool 没错,我上面的几种写法都是使用了属性。   回复  引用  查看    

#40楼  2006-11-11 11:42 roogeer[匿名] [未注册用户]

不错,写得很好,继续. 支持.   回复  引用  查看    

#41楼 [楼主] 2006-11-12 17:04 TerryLee      

@roogeer[匿名] 谢谢,后面还会继续   回复  引用  查看    

#42楼  2006-11-13 14:50 Amy[匿名] [未注册用户]

写的很好啊。希望继续。呵呵   回复  引用  查看    

#43楼 [楼主] 2006-11-13 16:40 TerryLee      

@Amy[匿名] 谢谢 会坚持写完:)   回复  引用  查看    

#44楼  2006-11-21 12:59 zheng yue [未注册用户]

写得很好.我有一个实际问题想请教一下. 我有两个模块. 登录和记费. 我在登录模块创建一个Sigleton实例,并在存入用户信息. 然后我在记费模块用 Sigleton MySigletonUser = Sigleton.Instance();调用以创建的实例. 这样Sigleton 保证了实例的唯一.所以其他模块调用MySigletonUser 时, 都调用同一用户, 同一时间的用户信息. 问题是如果Garbage colletor 清除了我在登录模块创建一个Sigleton实例.那末其他模块调用MySigletonUser 时 会产生新的实例.原来的用户信息就没.我如何能避免这种情况呢? 谢谢.   回复  引用  查看    

#45楼  2006-11-21 13:03 zheng yue [未注册用户]

写得很好.我有一个实际问题想请教一下. 我有两个模块. 登录和记费. 我在登录模块创建一个Sigleton实例,并在存入用户信息. 然后我在记费模块用 Sigleton MySigletonUser = Sigleton.Instance();调用以创建的实例. 这样Sigleton 保证了实例的唯一.所以其他模块调用MySigletonUser 时, 都调用同一用户, 同一时间的用户信息. 问题是如果Garbage colletor 清除了我在登录模块创建的Sigleton实例.那末其他模块调用MySigletonUser 时 会产生新的实例.原来的用户信息就没了.我如何能避免这种情况呢? 谢谢.   回复  引用  查看    

#46楼 [楼主] 2006-11-21 13:05 TerryLee      

@zheng yue 纳闷,为什么不用Session呢?   回复  引用  查看    

#47楼  2006-11-24 22:50 zheng yue [未注册用户]

It is winform application. I do not have session out of box. I am evaluating the benefit of using Composite UI Application Block (CAB) CAB provide something call Workitem state. It can be used for whole app or each individual Use Case. However, it is big learning curve for CAB, including IoC, MVP, event broker and etc. If I use singleton pattern to implement business object to store user information like Workitem in CAB, I have to have way to control the life cycle of those business object.   回复  引用  查看    

#48楼  2006-11-29 09:37 king[匿名] [未注册用户]

@zheng yue I thought it's not proper to use singleton pattern for user information. There should be lots of users, they are different to each other. How can you use same instance to take care various users? The logic is puzzled. I thought you need a way to keep persistence.   回复  引用  查看    

#49楼  2006-12-14 15:48 zengjun[匿名] [未注册用户]

想问一下 如果并发运行这个对象 因为有锁会不会等待前一个运行完成后才能运行,如果要等待,如果并发性大会等待很久   回复  引用  查看    

#50楼 [楼主] 2006-12-14 23:57 TerryLee      

@zengjun[匿名] 并不是任何时候都要用,在使用单件时还得考虑具体的情况,最好不要使用Double Lock   回复  引用  查看    

#51楼  2006-12-19 10:27 蓝星 [未注册用户]

受用,学习中,谢谢!!!   回复  引用  查看    

#52楼  2006-12-22 15:32 hnsdxujunyi [未注册用户]

同样受教菲浅,继续支持,并且坚持学习。 熟读多遍,思考再三,重视发言,只问困惑。   回复  引用  查看    

#53楼 [楼主] 2006-12-23 16:21 TerryLee      

@蓝星 :)   回复  引用  查看    

#54楼 [楼主] 2006-12-23 16:22 TerryLee      

@hnsdxujunyi :)   回复  引用  查看    

#55楼  2006-12-27 11:35 Charly      

8错,最近开始学习设计模式。。。   回复  引用  查看    

#56楼  2006-12-27 12:54 边城浪 [未注册用户]

用.NET2.0中静态类来替换Singleton模式是不是更好一些呢?   回复  引用  查看    

#57楼  2007-01-10 21:41 yanzimywife [未注册用户]

写的不错,支持   回复  引用  查看    

#58楼  2007-01-11 16:46 qcrsoft [未注册用户]

在程序中引用了WEB Services,我想这个web services只有一个实例,单件模式能不能派上用场呢?我一时想不明白,高手们给点拨一下,感激!   回复  引用  查看    

#59楼  2007-01-12 20:56 MingG      

刚学习设计模式,看了一头雾水, terrylee大哥的文章 爽~~` 以后有不懂的地方就来这逛喽...   回复  引用  查看    

#60楼 [楼主] 2007-01-15 08:38 TerryLee      

@MingG 欢迎常来:)   回复  引用  查看    

#61楼  2007-02-06 17:02 [匿名] [未注册用户]

学习,支持   回复  引用  查看    

#62楼  2007-02-26 20:28 sapphire [未注册用户]

在“5.延迟初始化”中: public sealed class Singleton { Singleton() { } ...... 是不是要写为: public sealed class Singleton { internal Singleton() { } ...... 不然在Nested类中无法 new Singleton()   回复  引用  查看    

#63楼  2007-03-22 21:37 李大力      

受益匪浅   回复  引用  查看    

#64楼  2007-04-06 15:25 cqy [未注册用户]

数据库访问类,有必要使用单件模式么?   回复  引用  查看    

#65楼  2007-04-13 13:24 wenchenxi@163.com [未注册用户]

///开始计数 MyCounter.Add(); results += "线程"; results += Thread.CurrentThread.Name.ToString() + "——〉"; results += "当前的计数:"; results += MyCounter.GetCounter().ToString(); //results += "/n"; Console.WriteLine(results); } ///清空显示字符串 results = ""; 我测试了,上面的代码没有线程安全性,即输出结果可能不能够控制就是本次增加后的结果。 所以应该把这段代码锁定。lock(o)   回复  引用  查看    

#66楼  2007-04-13 16:29 jxdworld [未注册用户]

谢谢,很详细,也很清楚!   回复  引用  查看    

#67楼  2007-05-10 17:32 担当 [未注册用户]

不错,受益匪浅   回复  引用  查看    

#68楼  2007-05-13 20:31 逍遥剑客      

是不是有必要在 DoSomeWork()的for 循环中lock(MyCounter)?? 要不然在在该多线程的例子中不安全!   回复  引用  查看    

#69楼  2007-06-06 09:32 贾宝玉 [未注册用户]

真牛!   回复  引用  查看    

#70楼  2007-06-20 16:58 xiekeli [未注册用户]

一起研究OO,多赐教:借宝地宣传一下自己的blog,真诚期待各位的指点:http://xiekeli.blogbus.com/index.html   回复  引用  查看    

#71楼  2007-06-26 20:14 JBoy      

学习ing! 受益了   回复  引用  查看    

#72楼  2007-06-26 20:54 JBoy      

有个问题,请教一下老大:在双重锁定实现的代码中, if (instance==null) { lock (padlock) { if (instance==null) //这个决断有没有必要? { instance = new Singleton(); } } } 有没有必须在锁定后再来判断instance == null呢? 既然已经锁定了,只能有一个线程来访问,就没有必要再决断对象是否为空了。我是菜鸟,不怎么懂的。   回复  引用  查看    

#73楼  2007-06-26 20:58 JBoy      

还有一个问题:为什么在应用程序中很少用双重锁定现实单例模式?   回复  引用  查看    

#74楼  2007-06-26 21:16 JBoy      

再一个问题(我的问题是不是太多了?):第五种模式实现,在多线程的情况下是不安全的,是吗?   回复  引用  查看    

#75楼  2007-06-30 14:05 protorock [未注册用户]

楼主给的例子有问题。运行后的结果出现: 线程Thread 1-->当前计数值:2 …… 线程Thread 2-->当前计数值:2 例子程序实现了singleton模式,但是没有解决同步问题!原因很简单,你考虑考虑吧 :-)   回复  引用  查看    

#76楼  2007-06-30 14:08 protorock [未注册用户]

我的计算机是“至强”双核CPU   回复  引用  查看    

#77楼  2007-07-08 03:37 yanzimywife [未注册用户]

当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 这句话没有看懂啊!   回复  引用  查看    

#78楼  2007-08-07 18:32 监控局域网 [未注册用户]

不错。写程序不学设计模式是写不出好程序的。多谢楼主。   回复  引用  查看    

#79楼  2007-08-23 15:33 华为菜鸟 [未注册用户]

看了N次了,每次的感觉都不一样! 支持!!支持!!感谢楼主的无私! 同时我更佩服楼主的人品。做人做到这样,真的是很成功! 学习了!!   回复  引用  查看    

#80楼  2007-09-17 20:30 XuQ      

感觉双重锁那里的第二次instance == null 判断没有必要,terrylee为什么要加上呢,不解,请指教   回复  引用  查看    

#81楼  2007-09-25 10:48 高原之上      

谢谢   回复  引用  查看    

#82楼  2007-10-31 11:55 deepfreesea [未注册用户]

@XuQ A处 if (instance == null) { B处 lock (syncRoot) { C处 if (instance == null) instance = new DoubLockSigleton(); } } 对象为空时,假设有两个线程①②,当①在A处判断返回true,进入B处,此时,②也在A处判断返回true,进入B处,①线程锁定,并创建对象实例,解锁,然后②锁定程序,到达C处,如果C处不判断,则有创建了一个对象实例,形成多个实例   回复  引用  查看    

#83楼  2007-10-31 12:22 XuQ      

@deepfreesea 呵呵,忽然开朗,看来得看看线程并发类的文章了   回复  引用  查看    

#84楼  2007-11-06 16:33 专研.NET      

这东东对我有点难哈,学习中~~~ 支持楼主!   回复  引用  查看    

#85楼  2007-11-07 20:17 scotoma      

在博客园逛了一年的了...现在才理解这些!嗨..好好的努力   回复  引用  查看    

#86楼  2007-12-17 11:32 Sam Lin      

@protorock 我也出现这个情况:线程Thread 1-->当前计数值:2 …… 线程Thread 2-->当前计数值:2 不知如何解决呢?是什么原因造成的呢?谢谢   回复  引用  查看    

#87楼  2008-02-17 20:00 ♂风车车.Net      

好文章,谢谢大哥! 报告!我在转载您的文章,我的转载后的地址是:http://www.cnblogs.com/xray2005/archive/2008/02/17/1071492.html   回复  引用  查看    

#88楼 [楼主] 2008-02-21 19:19 TerryLee      

@♂风车车.Net 随便转载,呵呵,只要保留原文出处就行了:)   回复  引用  查看    

#89楼  2008-04-15 11:26 阿瑞--16hi      

楼主文笔流畅,解说透彻明了,不支持都不行~~~   回复  引用  查看    

#90楼  2008-05-08 19:18 周密 [未注册用户]

不错啊 ^_^   回复  引用  查看    

#91楼  2008-05-11 15:11 wayich      

学习中。。。。   回复  引用  查看    

#92楼  2008-06-20 17:01 杲頔      

您好:我有一个小问题希望得到您的解答: using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { CC1.GetC().A(); CC2.GetC().A(); Console.Read(); } } public class CC1 { private CC2 c2 = CC2.GetC(); private static CC1 c1=new CC1(); public static CC1 GetC() { return c1; } public void A() { c2.Write(); } public void Write() { Console.WriteLine("CC1的Write()"); } } public class CC2 { private CC1 c1 = CC1.GetC(); private static CC2 c2 = new CC2(); public static CC2 GetC() { return c2; } public void Write() { Console.WriteLine("CC2的Write()"); } public void A() { c1.Write(); } } } 在这里运行到 public void A() { c1.Write(); } 的时候就会提示c1未将对象引用设置到对象的实例。 不知道为什么,希望您给帮我看看,谢谢。

#1楼  2005-12-09 15:15 KingWorld [未注册用户] 回复  引用  查看     #2楼 [楼主] 2005-12-09 15:46 Terrylee