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

作用:保证一个类只能有一个实例。并提供一个访问它的全局访问点。属于创建型模式。
实现要点:一.使用一个静态成员变量作为“全局”实例,这样就确保了唯一性
              二.使用静态的成员函数instance()替代new来获取该类的实例,这样就提供了全局的访问点
              三.构造函数设为private,使调用者不能用new来创建此类的实例
代码:两种方法实现单件模式,一种是Early initialization,一种是Lazy Initialization。

方法一:

// Early initialization
     class  EarlySingleton
    {
        
private   static  EarlySingleton earlyInstance  =   new  EarlySingleton();
        
private  EarlySingleton()
        {

        }
        
public   static  EarlySingleton Instance()
        {
            
return  earlyInstance;
        }
    }

 

方法二:

// Lazy Initialization
     class  LazySingleton
    {
        
private   static  LazySingleton lazyInstance;
        
private  LazySingleton()
        {

        }
        
public   static  LazySingleton Instance()
        {
            
if  (lazyInstance  ==   null )
            {
                lazyInstance 
=   new  LazySingleton();
            }
            
return  lazyInstance;
        }
    }

 

 深入:观察代码可以看出,方法二的静态变量只有在需要使用的时候才实例化,与方法一不管什么时候都一直存在相比,更加节省系统资源。但是方法二也不是没有问题——当使用多线程时,由于可能的线程异步,某个线程已经开始实例化lazyInstance但还未完成,而另一个线程在判断lazyInstance == null时仍然为true,从而又实例化一个,这将招致严重的错误。解决方法有三个:这三个方法是:
 1、使用 [MethodImpl(MethodImplOptions.Synchronized)] ,指定instance()方法同时只能被一个线程使用

 2、lock(myObject),是对一个对象加互斥锁,只允许一个线程访问其后大括号中语句块,直到该语句块的代码执行完才解锁,解锁后才允许其他的线程执行其语句块。

3、使用 Mutex  类的 WaitOne 方法。

按这三个方法修改后的代码分别如下:

1.

using  System.Threading;
using  System.Runtime.CompilerServices; 
// Lazy Initialization
     class  LazySingleton
    {
        
private   static  LazySingleton lazyInstance;
        
private  LazySingleton()
        {

        }
        [MethodImpl(MethodImplOptions.Synchronized)] 
// 方法的同步属性 
         public   static  LazySingleton Instance()
        {
            
if  (lazyInstance  ==   null )
            {
                lazyInstance 
=   new  LazySingleton();
            }
            
return  lazyInstance;
        }
    }

2.

using  System.Threading;
// Lazy Initialization
     class  LazySingleton
    {
        
private   static  LazySingleton lazyInstance;
        
static   object  myObject  =   new   object (); 
        
private  LazySingleton()
        {

        }
        
public   static  LazySingleton Instance()
        {
            
lock  (myObject)
            {
                
if  (lazyInstance  ==   null )
                {
                    lazyInstance 
=   new  LazySingleton();
                }
                
return  lazyInstance;
            }
        }

    }

3.

using  System.Threading;
// Lazy Initialization
     class  LazySingleton
    {
        
private   static  LazySingleton lazyInstance;
        
static   object  myObject  =   new   object ();
        
private   static  Mutex mut  =   new  Mutex();
        
private  LazySingleton()
        {

        }
        
public   static  LazySingleton Instance()
        {
            mut.WaitOne(); 
           
            
if  (lazyInstance  ==   null )
            {
                lazyInstance 
=   new  LazySingleton();
            }

            mut.ReleaseMutex(); 
            
return  lazyInstance;
        }
    }

 

发现很多设计模式的作者都是写到此为止。其实还未结束,James.W.Cooper在他的书里指出:当唯一的实例已经存在时,最好给调用者抛出一个明确的异常信息。这个很有道理,如果单件实例已存在,而调用者不知道,我们不吭声就把这个已存在的单件实例返回给他,很有可能导致他犯更大的错误。

修改Instance()中代码:

if  (lazyInstance  ==   null )
{
   lazyInstance 
=   new  LazySingleton();
}
else
{
   
throw   new  Exception( " Singleton should be init just once " );
}

 

 

你可能感兴趣的:(Singleton)