单例模式

单例模式的目的

创建对象,确保对象的唯一性,在同一个系统中,对象只有一个实例.让类自己负责保存它的唯一实例,提供一个访问实例的方法.

单例模式概述

单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

要点

  • 类只能有一个实例
  • 类自己负责创建实例
  • 提供访问实例的方法

实现分类

  • 饿汉式
  • 懒汉式

饿汉式

pulic class Singleton{
  //唯一实例
  private static Singleton instance = new Singleton();

  //只能由类自己负责创建实例
  private Singleton(){

  }

}
//外部访问实例的方法
public static getInstance(){
  return instance;
}

从代码中可以看出,在定义静态变量的时候就实例化了单例类.在类加载的时候,静态方法会先加载,所以单例对象在类加载的时候九被创建了,静态变量只加载一次,可以保证单例对象的唯一性,并且是线程安全的.但是在类加载的时候就创建,会影响程序的效率.

懒汉式

public class Singleton{
  //唯一实例
  private static Singleton instance = null;

  //只能由类自己负责创建实例
  private Singleton(){

  }

  //外部访问实例的方法
  public static getInstance(){
    if (interface  == null)
        instance = new Singleton();
    }
    return instance;
  }    
}

懒汉式在需要的时候才实例化,在类加载的时候不进行实例化,能起到懒加载的作用,但是如果在多线程的情况下,比如线程A和线程B同时调用getInstance(),可能会导致并发问题,所以要在getInstance()前加上synchronized进行同步,但是这样每次都要判断,会降低访问速度.可以用双重检查锁.
双重检查锁的第一次检查是检查实例是否存在,如果不存在再进入下面的同步块,而不是直接进入同步块.第二重检查是进入同步块后,再检查实例是否存在,如果不存在,就在同步的情况下创景实例.

/**
*双重检查锁的单例模式
*/

public class Singleton{
  /**
    * 对保存实例的变量添加volitile的修饰
    * 唯一实例
  */
  private volatile static Singleton instance = null;

  //只能由类自己负责创建实例
  private Singleton(){

  }

  //外部访问实例的方法
  public static getInstance(){
    //第一重检查,检查实例是否存在,如果不存在,再进入同步代码块
    if (interface  == null)
        //锁定代码块
        synchronized (Singleton.class){
          //第二重检查
          if (instance == null) {
                instance = new Singleton();//创建单例实例
          }
        }
    }
    return instance;
  }    
}

更好的实现方式

饿汉单例模式在类加载的时候就会创建,不能实现延时加载,如果以后不用,还会占据内存,还会影响程序的加载效率.懒汉单例模式需确保线程安全,性能会受到影响.比较好的实现方式是结合二者的优点,使用静态内部类来实现单例模式.

public class Singleton {

    /**
     * 类级的内部类,也就是静态类的成员式内部类,
    *该内部类的实例与外部类的实例没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载
     */
     private static class SingletonHolder{
        /**
         * 静态初始化器,由JVM来保证线程安全
         */
        private static Singleton instance = new Singleton();
    }

    /**
     * 私有化构造方法
     * 只能由类自己负责创建实例
     */
    private Singleton(){

    }

    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

使用静态内部类,能实现延时加载,保证线程安全,又不影响系统性能.

枚举类型实现

根据<Effective Java>第二版,单元素的枚举类型已经成为实现Singleton的最佳方法。

/**
 * 使用枚举来实现单例模式
 *
 */
public class Singleton {

    /**
     * 定义一个枚举的元素,它就代表了Singleton的一个实例
     */
    uniqueInstance;

    /**
     * 单例的方法
     */
    public void singletonOperation(){
        //功能树立
    }
}

单例的使用场景

系统只需要要一个实例对象,而且客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容