设计模式--单例模式探究

来源:互联网 发布:share.js用法 编辑:程序博客网 时间:2024/06/08 11:00

最近写程序经常用到单例模式,比如对于一个对象想让它唯一化,或者想在各个地方使用这个对象,但又必须是相同的地址,所以这里将常用的几种单例写法分享给大家。


第一种:恶汉式:

优点:在当前单例的类加载的时候单例的对象便已经创建,所以效率特别高

缺点:在内存上会占用一定的空间

  1. public class SingleUtil{  
  2.   private SingleUtil(){}
  3.   private static  SingleObj singleObj = new SingleObj ();  
  4.   public static SingleObj getInstance(){  
  5.     return singleObj ;  
  6.   }  
  7. }  

点评:当需要速度并且内存足够时,可以采用此种方式


第二种:基础懒汉式:

优点:需要单例的对象只有在调用这个getInstance()方法时才会创建,所以提高了内存使用

缺点:因为在调用方法的时候才会创建对象,所以时间上稍微有点慢。

  1. public class SingleUtil{  
  2. private SingleUtil(){}
  3.   private static  SingleObj singleObj = null;  
  4.   public static SingleObj getInstance(){  
  5. if(singleObj == null){
  6. singleObj = new SingleObj ();
  7. }
  8.     return singleObj ;  
  9.   }  
  10. } 

点评:当不计较使用速度并且需要内存更加有效率的话,使用此模式

第三种:一般同步懒汉式:

优点:比一般的懒汉式多了一个同步关键字,但依旧不能支持多线程的场景

缺点:这种简单的同步其实有时候并不能完全同步

  1. public class SingleUtil{  
  2. private SingleUtil(){}
  3.   private static  SingleObj singleObj = null;  
  4.   public static SingleObj getInstance(){  
  5. if(singleObj == null){
  6. synchronized(this){
  7. singleObj =new SingleObj ();
  8. }
  9. }
  10.     return singleObj ;  
  11.   }  
  12. } 

点评:建议不使用这种方式,如果是多个线程同时访问时,当第一个线程拿到this锁并且其中new对象的过程还没有执行完成,另一个线程判断singleObj 为空,

那么它会进入到if条件里面,当第一个线程结束执行后,第二个会继续拿到锁,并且执行new语句,又创建一个对象。这样的同步是没有效果的。


第四种:完全同步懒汉式:

优点:这种同步方式相比较第三种来说,安全性就提高很多了,可以支持多线程的场景

缺点:因为是多线程所以性能上面相比较别的方式来说还是有一定差距的。

  1. public class SingleUtil{  
  2. private SingleUtil(){}
  3.   private static  SingleObj singleObj = null;  
  4.   public static SingleObj getInstance(){  
  5. if(singleObj == null){
  6. synchronized(this){
  7. if(singleObj == null){
  8. singleObj =new SingleObj ();
  9. }
  10. }
  11. }
  12.     return singleObj ;  
  13.   }  
  14. } 

点评:如果是并发场景的话,建议使用这种方式创建单例对象。

第五种:内部类创建单例对象:
优点:省去了内部类的加载,需要创建单例对象的时候再创建,最主要是当SingleUtil类加载的时候,单例对象并不会被加载
缺点:构造比较复杂,结构也比较复杂。
  1. public class SingleUtil{  
  2. private SingleUtil(){}
  3. static class BollSingle{
  4. private static final SingleObj singleObj = singleObj = new SingleObj (); 
  5. } 
  6.   public static SingleObj getInstance(){  
  7.     return BollSingle.singleObj;  
  8.   }  
  9. } 

点评:此种方式也是比较推荐使用的,静态内部类中单例对象是final的,这样当我们利用内部类调用singleObj 对象时,内部类并不会被加载,
并且我们还可以控制得到单例的时间,当调用getInstance()方法时才会加载,并且也少去了if的判断。

第六种:枚举法
此种不太常用,所以也就不介绍了,如有感兴趣的朋友可以网上再查一查。

如果有什么不对的地方,欢迎大家一块交流,一块探讨哦。









原创粉丝点击