详述.NET设计模式:单件模式(2)

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

    5.延迟初始化

 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


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

    实现要点

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

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

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

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

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

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

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

    优点

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

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

缺点

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

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

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

    适用性

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

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

    应用场景

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

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

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

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

    完整示例

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


 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

    总结

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

Tags:  Singleton 大话设计模式 软件设计模式 mvc设计模式 单件模式 设计模式

延伸阅读

最新评论

发表评论