单利模式与缓存功能的实现

     在《设计模式》一书中,作者这样来叙述单例模式的:确保一个类只有一个实例并提供一个对它的全局访问指针。
     为了确保全局只有一个实例,所有访问这个类的实例的指针的地址保证相同,必须满足下面的几个条件:
   
  1. 私有的构造函数;
  2. 自行创建这个事例;
  3. 静态的实例化方法提供全局唯一实例。
    在单例模式中又可以分为饿汉式单利模式和懒汉式单例模式。所谓饿汉式单例模式就是在类被访问时这个唯一的实例便被创建,而不管他是否会被使用;而懒汉式单例模式在类被加载的时候不会被实例化,只有第一次使用静态实例化方法访问的时候才会被实例化。
    从理论上分析饿汉式单例模式实现简单,但却会在一定程度上降低运行效率,而懒汉式单例模式虽然不会有运行效率的问题,实现方法却有些复杂。下面是这两种单例模式的代码示例:

饿汉式单例模式
public class EagerSingleton 

    
private static final EagerSingleton m_instance = new EagerSingleton(); 
    
/// <summary> 
    
/// 私有的默认构造子 
     
/// </summary>

    private EagerSingleton() { } 
    
/// <summary> 
    
/// 静态工厂方法 
     
/// </summary>

    public static EagerSingleton getInstance() 
    
{
        
return m_instance; 
    }

}
 

懒汉式单例模式
    public class LazySingleton 
    

        
private static LazySingleton m_instance = null

        
/// <summary>
        
/// 私有的默认构造子,保证外界无法直接实例化
        
/// </summary>

        private LazySingleton() { } 

        
/// <summary>
        
/// 静态工厂方法
        
/// </summary>
        
/// <returns>返还此类的惟一实例</returns>

        public static LazySingleton getInstance() 
        

            
if (m_instance == null) // 1. 在多线程模式下有可能同时有两个以上的线程通过此判断
            
{
                m_instance 
= new LazySingleton(); 
            }
 
            
return m_instance; 
        }

    }

也许您会说难道使用protected或者public的构造函数就不可以了吗?理论上是不可以的,如果使用protected构造函数就不能够保证在子类中不会再次被实例化,而使用public构造函数就更加不言而喻了。
也许您已经看出来在上例代码中的懒汉式单例模式只能运行在单线程的程序中,而对于多线程便是不安全的了,正如代码中的注释。如果有两个以上的线程同时通过判断,那就会在接下来的过程中产生两个以上的对象实例,而m_instance变量最终会指向最后一次实例化的结果,但是并不能保证此实例化函数的返回结果的指针指向同一个实例。也就是在多线程的模式下已经违背了单例模式的原则,为了能够保证全局的唯一实例,可以采用双重验证的方法。如下代码所示:

    
public class LazySingleton 
    

        
private static LazySingleton m_instance = null
        
private static object synRoot=new object() ;

        
/// <summary>
        
/// 私有的默认构造子,保证外界无法直接实例化
        
/// </summary>

        private LazySingleton() { } 

        
/// <summary>
        
/// 静态工厂方法
        
/// </summary>
        
/// <returns>返还此类的惟一实例</returns>

        public static LazySingleton getInstance() 
        

            
if (m_instance == null
            
{
                
lock(synRoot)
                
{
                    
if (m_instance == null
                    
{
                        m_instance 
= new LazySingleton(); 
                    }

                }

            }
 
            
return m_instance; 
        }

    }


关于单例模式详细内容可以参考如下内容:
http://xxol.net/Edu/Development/Java/0541312241282488.htm
http://xxol.net/Edu/Development/Java/0541312240656996.htm
http://xxol.net/Edu/Development/Java/0541312240591257.htm
http://xxol.net/Edu/Development/Java/0541312235356276.htm

登记式多例模式是在单例模式的基础上延伸出来的,利用关键字来获取全局唯一对象实例。因此简单的缓存功能的实现也可以借助这种方法来实现,不同的是对象的实例化不是由缓存容器来实现,而是由缓存容器之外的方法去创建,然后跟据关键字从缓存容器获取这一实例,或者根据关键字来修改和删除这个实例。由此可见缓存器的功能要比登记时多例模式的功能更加灵活,而不会仅仅局限在对象实例的访问。

posted on 2005-07-23 15:40  Edward.Net  阅读(1433)  评论(1编辑  收藏  举报

导航