设计模式学习之路——Singleton 单件模式

在程序设计过程中,有很多情况需要保证一个类只有一个实例.这时候就需要使用单件模式了。

保证一个类仅有一个实例,并提供一个该实例的全局访问点。——《设计模式》GoF

结构(Struct)

 

设计模式学习之路——Singleton 单件模式

 

1 使用静态方法创建单件

让一个类只有一个实例,最容易的方法是在类中嵌入一个静态变量,并在第一个类实例中设置该变量,而且每次进入构造函数都要检查。不管类有多少个实例,静态变量只能有一个实例。为了防止类被多次实例化,我们把构造函数声明为私有的,这样只能在类的静态方法里创建一个实例。

单线程环境下Singleton模式的实现

 

代码
public   class  Singleton
    {
        
private   static  Singleton instance;
        
private  Singleton() {}

        
public   static  Singleton Instance
        {
            
get  
            {
                
if  (instance  !=   null )
                {
                    instance 
=   new  Singleton();
                }
                
return  instance;
            }
        }    
}

 

 

 

单线程Singleton模式的几个要点

1. Singleton模式中的实例构造器可以设置为protected以允许子类派生。

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

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

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

5. 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singlet类的多个实例对象。

 

 

多线程环境下Singleton模式实现

 

代码
public   class  Singleton
    {
        
private   static   volatile  Singleton instance;
        
private   static   object  lockHelper  =   new   object ();

        
private  Singleton() { }

        
public   static  Singleton Instance
        {
            
get
            {
                
if  (instance  !=   null )
                {
                    
lock  (lockHelper)
                    {
                        
if  (instance  !=   null )
                        {
                            instance 
=   new  Singleton();
                        }
                    }
                }
                
return  instance;
            }
        }
    }

 

 

 

代码
public   class  Singleton
    {
        
public   static   readonly  Singleton Instance;

        
static  Singleton()
        {
            Instance 
=   new  Singleton();
        }

        
private  Singleton() { }

    }

 

 

上面的方式等同于下面的实现方式:

 

public   class  Singleton
    {
        
public   static   readonly  Singleton Instance =   new  Singleton();
        
private  Singleton() { }

    }

 

 

 

 

 

2提供一个单件的全局访问点

 

由于使用单件可以提供一个类的全局访问点,即使C#中没有全局变量,设计程序时也必须为整个程序提供引用单件的方法。

一种解决方案是在程序的开头创建单件,并将其作为参数传递到需要使用它的类中。

 

     Singleton instance = Singleton.Instance;
     Test test
=   new Test(instance);

 

 

 

这种方法的缺点是,在某次程序运行中,可能不需要所有的单件,,这样会影响程序的性能。

另一种更灵活的解决方案是,在程序中创建一个所有单件类的注册表,并使注册表始终是可用的,每次实例化一个单件,都将其记录在注册表中。程序的任何部分都能使用标识字符串访问任何一个单件实例,并能取回相应的实例变量。

注册表方法的缺点是减少了类型检查,因为注册表中的单件表可能把所有的单件都保存成对象类型,例如,hashtable中的对象类型,另外,注册表本身也有可能是一个单件,必须使用构造函数或者其他set函数把他传递给程序的所有部分。

提供一个全局访问点的最常用方式是使用类的静态方法。类名始终是可用的,静态方法只能由类调用,不能由类的实例调用,所以,不管程序中有多少个地方调用该方法,永远只能有一个这样的类实例。

你可能感兴趣的:(Singleton)