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

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

饿汉式单例模式
None.gif public   class  EagerSingleton 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
private static final EagerSingleton m_instance = new EagerSingleton(); 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary> 
InBlock.gif    
/// 私有的默认构造子 
ExpandedSubBlockEnd.gif     
/// </summary>

ExpandedSubBlockStart.gifContractedSubBlock.gif    private EagerSingleton() dot.gif{ } 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary> 
InBlock.gif    
/// 静态工厂方法 
ExpandedSubBlockEnd.gif     
/// </summary>

InBlock.gif    public static EagerSingleton getInstance() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return m_instance; 
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
 

懒汉式单例模式
None.gif      public   class  LazySingleton 
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif
InBlock.gif        
private static LazySingleton m_instance = null
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 私有的默认构造子,保证外界无法直接实例化
ExpandedSubBlockEnd.gif        
/// </summary>

ExpandedSubBlockStart.gifContractedSubBlock.gif        private LazySingleton() dot.gif{ } 
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 静态工厂方法
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns>返还此类的惟一实例</returns>

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

ExpandedBlockEnd.gif    }

也许您会说难道使用protected或者public的构造函数就不可以了吗?理论上是不可以的,如果使用protected构造函数就不能够保证在子类中不会再次被实例化,而使用public构造函数就更加不言而喻了。
也许您已经看出来在上例代码中的懒汉式单例模式只能运行在单线程的程序中,而对于多线程便是不安全的了,正如代码中的注释。如果有两个以上的线程同时通过判断,那就会在接下来的过程中产生两个以上的对象实例,而m_instance变量最终会指向最后一次实例化的结果,但是并不能保证此实例化函数的返回结果的指针指向同一个实例。也就是在多线程的模式下已经违背了单例模式的原则,为了能够保证全局的唯一实例,可以采用双重验证的方法。如下代码所示:
None.gif
None.gif    
public   class  LazySingleton 
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif
InBlock.gif        
private static LazySingleton m_instance = null
InBlock.gif        
private static object synRoot=new object() ;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 私有的默认构造子,保证外界无法直接实例化
ExpandedSubBlockEnd.gif        
/// </summary>

ExpandedSubBlockStart.gifContractedSubBlock.gif        private LazySingleton() dot.gif{ } 
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 静态工厂方法
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns>返还此类的惟一实例</returns>

InBlock.gif        public static LazySingleton getInstance() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
if (m_instance == null
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
lock(synRoot)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if (m_instance == null
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        m_instance 
= new LazySingleton(); 
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
return m_instance; 
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

None.gif

关于单例模式详细内容可以参考如下内容:
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

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

转载于:https://www.cnblogs.com/firstsee/archive/2005/07/23/198701.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值