`

单例模式

阅读更多

一. 什么是单例模式

   确保一个类只有一个实例, 并提供一个全局的访问点

 

二. 单例模式的特点

   1. 单例模式只能有一个实例。

   2. 单例类必须创建自己的唯一实例。

   3. 单例类必须向其他对象提供这一实例。

 

三, VS 静态类

  1. 单例可以继承和被继承,方法可以被override,而静态方法不可以。

  2. 静态方法中产生的对象会在执行后被释放,进而被GC清理,不会一直存在于内存中

  3. 静态类会在第一次运行时初始化,单例模式可以有其他的选择,即可以延迟加载。

  4. 基于2, 3条,由于单例对象往往存在于DAO层(例如sessionFactory),

      如果反复的初始化和释放,则会占用很多资源,而使用单例模式将其常驻于内存可以更加节约资源。

  5. 静态方法有更高的访问效率。

  6. 单例模式很容易被测试。

 

四, 单例的实现

   这边只介绍三种,懒汉式, 饿汉式和静态内部类

  1, 懒汉式:  先实例化

   注意点: 构造器私有化,私有静态自实例, 公共静态方法获取自实例

                为了考虑线程安全,最好加synchronized.

 

public class Singleton {
    private static Singleton instance;
    private SingletonDemo(){

    }
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance=new Singleton();
        }
        return instance;
    }
}

 

 

   缺点:每次通过getInstance方法得到singleton实例的时候都有一个试图去获取同步锁的过程。

            而众所周知,加锁是很耗时的。能避免则避免。 

     改进: 

 

public class Singleton {
    private static Singleton instance;
    private Singleton(){
       
    }
    public static Singleton getInstance(){
        if(instance==null){
            synchronized (Singleton.class){
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

 

 

 

2, 饿汉式: 先实例

     避免了多线程的同步问题,  但是在类加载就实例,达不到lazy loading的效果

 

 public class Singleton {  
     private static Singleton instance = new Singleton();  
     private Singleton (){}
     public static Singleton getInstance() {  
     return instance;  
     }  
 }  

 3, 静态内部类

 

      这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,

     只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类

 

public class Singleton {  
      private static class SingletonHolder {  
      private static final Singleton INSTANCE = new Singleton();  
     }  
      private Singleton (){}
      public static final Singleton getInstance() {  
          return SingletonHolder.INSTANCE;  
      }  
}

 

 

五, 扩展

   1, 多例

    顾名思义就是有多个实例.

    一种是每个请求就用一个新的实例来处理. 比如action.

   另一种是初始化多个实例供使用, 比如连接池.

 备注: 单例在spring中是默认的,如果要产生多例,则在配置文件的bean中添加scope="prototype";.

 

   2, 枚举实现

 

/**
 * 使用枚举的单例模式
 *
 */
public class EnumSingleton{
    private EnumSingleton(){}
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
    
    private static enum Singleton{
        INSTANCE;
        
        private EnumSingleton singleton;
        //JVM会保证此方法绝对只调用一次
        private Singleton(){
            singleton = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return singleton;
        }
    }
}

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics