单例模式详解
特点:
- 1、 保证从系统启动到系统终止, 全过程只会产生一个实例。
- 2、 当我们在应用中遇到功能性冲突的时候, 需要使用单例模式。
穷举法:
- 配置文件: 如果不是单例(针对于某一种功能的配置)
- Spring Context Factory 上下文
单例模式的七种写法:
- 懒汉式,需要用的时候才初始化
- 饿汉式,先实例化
- 注册登记式,相当于有个容器装在所有的实例,在实例产生之前先检查下容器看有没有,如果有就直接取出来,如果没有就先new一个放进去,然后给后面的人用,Spring IOC容器就是一种典型的注册登记单例。
七种单例模式:
- 懒汉式单例模式
/**
* 懒汉式单例模式
* @author DoubleChina
* @date 2018/1/6 11:51
*/
public class Singleton {
//1、第一步先将构造方法私有化,在反射面前,没用
private Singleton(){}
//2、然后先声明一个静态变量保存单例的引用
private static Singleton singleton=null;
//3、通过提供一个静态方法来获得单例的引用
public static Singleton getInstance(){
if (singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
- 懒汉式单例模式,保证线程安全
/**
* 懒汉式单例模式,保证线程安全
* @author DoubleChina
* @date 2018/1/6 11:51
*/
public class Singleton1 {
//1、第一步先将构造方法私有化,在反射面前,没用
private Singleton1(){}
//2、然后先声明一个静态变量保存单例的引用
private static Singleton1 singleton=null;
//3、通过提供一个静态方法来获得单例的引用
//为了保证多行程环境下正确访问,给方法加上同步锁synchronized
//存在一定的性能问题
public static synchronized Singleton1 getInstance(){
if (singleton==null){
singleton=new Singleton1();
}
return singleton;
}
}
- 懒汉式单例模式,双重锁检查
/**
* 懒汉式单例模式,双重锁检查
* @author DoubleChina
* @date 2018/1/6 11:51
*/
public class Singleton2 {
//1、第一步先将构造方法私有化,在反射面前,没用
private Singleton2() {
}
//2、然后先声明一个静态变量保存单例的引用
private static Singleton2 singleton = null;
//3、通过提供一个静态方法来获得单例的引用
//为了保证多行程环境下正确访问,给方法加上同步锁synchronized
//存在一定的性能问题
public static Singleton2 getInstance() {
if (singleton == null) {
synchronized (Singleton2.class) {
if (singleton == null) {
singleton = new Singleton2();
}
}
}
return singleton;
}
}
- 最牛B的方式实现单例模式
/**
* 最牛B的方式实现单例模式
* @author DoubleChina
* @date 2018/1/6 11:51
*/
public class Singleton4 {
//2.声明一个静态内部类
private static class InnerClass {
//final是为了防止内部将这个属性覆盖掉
private static final Singleton4 INSTANCE = new Singleton4();
}
//1.先把构造方法私有化
private Singleton4() {
}
//3.提供获取实例方法
//防止子类重写父类方法
public static final Singleton4 getInstance() {
return InnerClass.INSTANCE;
}
//内部类的初始化,需要依赖主类
//也就是说,当我们的JVM加载Singleton4类的时候,我们的InnerClass也同时被加载过来了
//目前还没有被实例化,需要等主类先实例化之后,内部类才开始实例化
//加final是为了防止子类重写父类方法
//
}
- 饿汉式
/**
* 饿汉式
* 单例模式,在类初始化,已经有自行的实例化
* @author DoubleChina
* @date 2018/1/6 11:51
*/
public class Singleton3 {
//1、第一步先将构造方法私有化,在反射面前,没用
private Singleton3() {
}
//2、声明变量,在类实例化之前就初始化变量,将对象引用保存
private static final Singleton3 singleton = new Singleton3();
//3、开放静态方法,获取实例,但是占用内存空间
public static Singleton3 getInstance() {
return singleton;
}
}
- 枚举式单例模式
/**
* 枚举式单例模式
* 不常用
* @author DoubleChina
* @date 2018/1/6 11:52
*/
public enum Singleton5 {
INSTANCE;
public void getInstance() {
}
}
- 登记式单例模式
/**
* 登记式单例模式
* 类似Spring里面的方法,讲类名注册,下次从里面直接获取
* @author DoubleChina
* @date 2018/1/6 11:52
*/
public class Singleton6 {
private static Map<String ,Singleton6> map=new ConcurrentHashMap<String, Singleton6>();
static {
Singleton6 single=new Singleton6();
map.put(single.getClass().getName(),single);
}
//保护默认的构造函数
protected Singleton6(){}
public static Singleton6 getInstance(String name){
if (name==null){
name=Singleton6.class.getName();
}
if (map.get(name)==null){
try {
map.put(name,(Singleton6)Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
}