设计模式 之 单件模式

单件模式

 

一、意图
        “单件”,从字面上理解也就是“一个零件”。我们平常说的单件模式,也是说要求我们整个应用程序中“有且只有”一个对象实例,这个对象实例为整个应用程序所共享,我们不希望也没必要创建多个这样的对象实例。

         既然,单件模式可以做到保证应用程序中有且只有一个对象实例,那么单件模式当然也可以保证应用程序有且只有N个对象实例或最多只有N个对象实例。

二、要点
1、怎样保证有且只有一个实例对象
要解决的问题:
1
、阻止客户代码随意创建对象(解决只有一个对象的问题)
2
、怎样创建对象(解决要有一个对象的问题)
        一般,我们要获取一个对象实例常用的方式是通过new关键字来硬编码创建对象实例。在面向对象中我们一般是先写个class,然后new对象实例时,通过调用class中的构造方法来实例话对象,这是一种很简单也很直接的方式。在这种情况下我们必须把class中相应的构造方法指定public访问权限,这样我们通过new关键字创建对象实例时,才能执行到相应的构造方法。下面是一个错误的实例:
由一个ClassA类定义如下
:
public class ClassA
{
        private ClassA() { } //
注意此处ClassA构造方法访问权限为
private
}
客户程序中创建ClassA对象实例
:
ClassA  a = new ClassA();//
该语句会出编译错误,因为不能执行到该类的构造方法。
也就是说,我们可以通过将类的构造方法访问权限设置为private来阻止其他程序创建该类的对象实例。

所以我们的单件模式代码可以初步写为:
public  class  Singleton
{
   private  static  Singleton  _instance;//static
申明的成员变量_instance,作用于整个应用程序域
   private  Singleton() { }
}
       
那么,我们怎样创建对象实例,让客户程序能够获取到Singleton对象实例
:
public  class  Singleton
{
     private  static  Singleton  _instance;
     private  Singleton() { }
     public  static  Singleton  GetInstance() //
客户程序通过GetInstance()来获取Singleton对象实例
     {
          if(_instance==null)
          {
                 
_instance = new  Singleton();//在类的内部,实例化对象实例
          }
          return  _instance;
     }
}
以上是一个最简单的单件模式,当然有待改进的地方。在多线程下,这样的实现方式可能会导致Singleton对象实例不唯一。
:AB两个线程,当A线程将要执行GetInstance()方法中的
_instance = new  Singleton() 语句而又没有执行完时,这时,_instance还为null。正巧,B线程也进入了GetInstance()方法,开始执行if(_instance==null)语句,因为A线程还没有创建好Singleton实例,所以if(_instance==null)将返回true值给B线程,B线程也将会执行到_instance = new  Singleton(),如果还有C线程也跟B线程一样,那么将会创建更多的Singleton对象实例。很快我们会想到线程锁:
public  class  Singleton
{
     private  static object  _lockObj = new object();//
锁对象
     private  static  Singleton  _instance;
     private  Singleton() { }
     public  static  Singleton  GetInstance() //
客户程序通过GetInstance()来获取Singleton对象实例

     {
          lock( _lockObj )
          {
               if( _instance==null )
               {
                      
_instance = new  Singleton();//
在类的内部,实例化对象实例
               }
               return  _instance;
          }
     }
}
但是,每次我们通过GetInstance()访问Singleton实例时都要lock一下,给线程加锁是比较耗资源的,改进如下
:
public  class  Singleton
{
     private  static object  _lockObj = new object();//
锁对象
     private  static  Singleton  _instance;
     private  Singleton() { }
     public  static  Singleton  GetInstance() //
客户程序通过GetInstance()来获取Singleton对象实例

     {
          if( _instance==null)//
_instance不为null时,以后的访问将不会被加锁
          {
                lock( _lockObj )
                {
                     if( _instance==null )
                     {
                            
_instance = new  Singleton();//在类的内部,实例化对象实例
                     }
                }
          }
          return  _instance;
     }
}
当然,还可以通过静态初始化来避免多线程下创建多个实例的问题,实现如下
:
public  class  Singleton
{
     private  static  Singleton  _instance = new  Singleton();
     private  Singleton() { }
     public  static  Singleton  GetInstance() //
客户程序通过GetInstance()来获取Singleton对象实例

     {
          return  _instance;
     }
}
也可以通过静态构造方法来初始化话_instance
对象,静态构造方法类静态变量直接赋值都没有多线程下多次实例化的问题。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值