简介
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,任务管理器、线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。在项目当中,系统启动读取配置文件就需要单例保证配置的一致性。
要点与实现
要点
- 一是某个类只能有一个实例
- 二是它必须自行创建这个实例
- 三是它必须自行向整个系统提供这个实例
实现
- 一是单例模式的类只提供私有的构造函数
- 二是类定义中含有一个该类的静态私有对象,
- 三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
实现单例模式方式
- 饿汉式
/** 饿汉式单例模式*/
public class Singleton {
private Singleton(){}//私有构造器
/*
* JVM只为静态分配一次内存,在加载类的过程中
* 完成静态变量的内存分配,天然的是线程安全的
*/
private static Singleton singleton=new Singleton();
public static Singleton getInstance(){//静态工厂方法
return singleton;
}
}
- 懒汉式
/** 懒汉式单例模式*/
public class Singleton {
private Singleton(){}//私有构造器
private static Singleton singleton=null;//静态变量
/**
* 延迟加载,需要的时候初始化,方法加锁,并发效率低
*/
public static synchronized Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
- 双重锁(饿汉式变种)
/**双重锁单例模式*/
public class Singleton {
private Singleton(){}//私有构造器
private static volatile Singleton singleton=null;//静态变量 可见性和指令重排序都保证
/**
* 避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。
*/
public static Singleton getInstance(){
if(singleton==null){
synchronized (Singleton.class){
if(singleton==null){
singleton=new Singleton();//非原子操作
}
}
}
return singleton;
}
}
- 静态内部类实现
/**静态内部类模式*/
public class Singleton {
private Singleton(){}//私有构造器
private static class SingletonClassInstance{
//static final 保证对象只会被赋值一次
private static final Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonClassInstance.instance;
}
}
- 静态代码块实现
/**静态代码块实现**/
public class Singleton {
private Singleton(){}//私有构造器
private static Singleton singleton=null;//静态变量
//静态代码块
static {
singleton=new Singleton();
}
public static Singleton getInstance(){
return singleton;
}
}
- 枚举类实现
/*枚举的单例模式*/
public class Singleton {
private Singleton (){}//私有构造
public static Singleton getInstance(){
return SingletonEnum.INSTANCE.getInstance();
}
/*目前最为安全的实现单例的方法是通过内部静态enum的方法来实现,
*因为JVM会保证enum不能被反射并且构造器方法只执行一次。*/
private enum SingletonEnum{
INSTANCE;
private Singleton singleton;
//JVM会保证此方法绝对只调用一次
private SingletonEnum(){
singleton=new Singleton();
}
public Singleton getInstance(){
return singleton;
}
}
}
反射攻击示例