设计模式之单件模式(Singleton)

      网上找到单件模式的C#实现方式,特记录下来,顺带加深记忆~~~
      对于它,有很多称呼:单件、单体、单例,都是在说它——Singleton,本文主要是用的单件。顾名思义,单,何为“单”,即唯一,仅有之意。
      单件模式的中心思想就是说 程序中的某一个类,我们在实例化它的时候,想让所得到的实例有,且仅有一个,这个就是单件模式。GOF书中对其描述为:“ 保证一个类仅有一个实例,并提供一个访问它的全局访问点”。
      单件模式在开发中还是比较常见的一种设计模式,比如,在开发WinForm的时候,做某个程序需要实现类似于工具箱之类的功能,这里就可以用到单件模式。在使用Photoshop等软件的时候,我们点击“视图”——“工具箱”,就可以在主界面上显示出工具箱了,但是,如果还有一个按钮,也是控制工具箱的显示的话,这两个事件都是实现了对工具箱的显示,如果依次触发,岂不是会生成很多个工具箱出来,所以,这里应该判断一下该工具箱的类是否已经存在(即判断对象是否为null)或者暂时性的隐藏了(即判对象的IsDisposed否为为true),但是,这样又产生了一个问题,那就是,只要有能够触发显示工具箱的事件,就应该出现该if的判断,这样就是造成了大量的代码重复,还有可能导致内存大量的消耗,而且万一要是需求有什么变化,修改起来相当的不方便。此时此刻,用单件模式就最好不过了(思路就是让工具箱这个类成为唯一的)。
      我们知道,在一个类中,如果其构造函数是私有的,那么,这个类是不能通过关键字“new”来实例化的,所以,单件模式正是利用了这一点,并且还利用了静态变量在全局中是恒定不变的这一特性,来实现了单件模式,即: 有,且仅有,一个实例
      在.NET中,如Type对象、HttpContext.Current等都使用了单件模式。
      说了这么多文字性的东西,还是用代码来实现才是最好的说明。
      一、首先建立一个普通的类
1  public   class  SampleSingleton
2  {
3  }
      二、将该类修改成以下样子(注意代码中的注释)
ContractedBlock.gif ExpandedBlockStart.gif 单件类
 1 public class SampleSingleton
 2 {
 3       // 创建一个静态本单件类型的私有变量
 4       // 该变量就是本类在程序中唯一的实例
 5       private static SampleSingleton _instance;
 6 
 7       // 私有的构造函数
 8       // 确保了外界不能通过“new”来实例化本类
 9       private SampleSingleton()
10       {
11       }
12 
13       // 向外界提供唯一的一个实例化本类的方法
14       // 也就是说,外界如果要获取本类的实例,只能通过此方法
15       public static SampleSingleton GetInstance()
16       {
17             // 如果实例不存在
18             if (_instance == null)
19             {
20                   // 则创建一个实例
21                   _instance = new SampleSingleton();
22             }
23 
24             // 最后,返回本类的实例
25             return _instance;
26       }
27 }
      简单的两步,就完成了单件类的创建。外界在调用的时候,只能通过“SampleSingleton.GetInstance()”来获取本类的实例,加之其又是静态的,所以就保证了本类的实例有且仅有一个。还可以通过类的内联初始化来实现单件模式,代码如下:
1  public   class  SampleSingleton
2  {
3         private  SampleSingleton()
4        {
5        }
6 
7         public   static   readonly  SampleSingleton Instance  =   new  SampleSingleton();
8  }
      通过内联创建的单件模式,在调用的时候,也是只能通过“SampleSingleton.Instance”来获取本的实例。差不多了,创建单件类的说明就到这里,在网上找一下,能够找到很多关于单件模式的示例,我这里就随便举一个例:用单件模式来实现一个计数的功能。
      首先,如上所示代码,建立一个计数的单件类,代码如下:
ContractedBlock.gif ExpandedBlockStart.gif 单件类计数器
 1 public class Counter
 2 {
 3       // 静态的私有计数器类实例
 4       private static Counter _counter = null;
 5 
 6       // 用于计数的私有变量
 7       private int _count = 0;
 8 
 9       // 私有计数器类构造函数
10       private Counter()
11       {
12             Console.WriteLine("开始计数");
13       }
14 
15       // 获取计数器实例的全局唯一方法
16       public static Counter GetInstance()
17       {
18             if (_counter == null)
19             {
20                   _counter = new Counter();
21             }
22 
23             return _counter;
24       }
25 
26       // 开始计数,并且显示出来
27       public void CountAndShow()
28       {
29             _count ++;
30             Console.WriteLine("单个对象被调用了{0}次", _count);
31       }
32 }
      然后,在外界调用该单件类,代码如下:
ContractedBlock.gif ExpandedBlockStart.gif 外界调用单件类方法
 1 public class TestSingleton
 2 {
 3       public static void Main(string[] args)
 4       {
 5             Console.WriteLine("计数器开始工作");
 6 
 7             for (int i = 0; i < 5; i++)
 8             {
 9                   Counter.GetInstance().CountAndShow();
10             }
11 
12             Console.ReadLine();
13       }
14 }
      但是,这又带来了另外的一个问题,那就是,如果是一个多线程的程序,多个线程同时访问上述的计数器类的“GetInstance()”方法,这样,就有可能会对计数器类创建多个实例,这时,就可以使用关键字“lock”来限制( 在MSDN中,lock的定义是:lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其它的线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。),但是在创建实例的时候,要进行“ 双检查”。
      所以,上述单件模式的代码可以修改为以下形式(MSDN):
ContractedBlock.gif ExpandedBlockStart.gif 多线程下的Singleton
 1 public class SampleSingleton
 2 {
 3       private static SampleSingleton _instance;
 4       private static object _obj = new object();
 5 
 6       private SampleSingleton()
 7       {
 8       }
 9 
10       public static SampleSingleton Instance
11       {
12             get
13             {
14                   if (_instance == null)
15                   {
16                         lock (_obj)
17                         {
18                               if (_instance == null)
19                               {
20                                     _instance = new SampleSingleton();
21                               }
22                         }
23                   }
24 
25                   return _instance;
26             }
27       }
28 }
      好了,差不多就这么多了,综上所述,创建单件模式(Singleton)必须具备以下三个条件:
      1、 私有构造函数(防止其他对象创建实例)
      2、 一个单件类型的私有变量
      3、 静态全局获取接口
      还有就是在使用中,要注意的几个问题:
      1、该模式一般不要支持ICloneable接口,因为可能导致多个对象实例。
      2、该模式一般不要支持序列化,同样是因为可能导致多个对象实例。
      3、该模式一般不建议使用到多线程环境中,同样,还是因为可能导致多个对象实例,如果要使用,一定要注意双检查。
      4、该模式只考虑到了对象创建的管理,没有考虑对像的销毁管理。不过,就支持垃圾回收的平台和对象的开销来讲,一般没有必要对其销毁进行特殊的管理。

转载于:https://www.cnblogs.com/jacksonwj/archive/2009/09/07/1562159.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值