通俗易懂的单例模式

单例模式自我心得

1、创建单例模式的几种方法

饿汉模式:也是思维上最常见的方式,我创建好了一个单例,无论何时来调用,都是可以的,反正我已经在这里了,无论你用或者不用,我都已经创建好了。

public class SingletonEHan{
	//私有化构造方法
    private SingletonEHan(){}

    //类初始化时立即加载这个对象
    private static  SingletonEHan instance = new SingletonEHan();

    //提供获取对象的方法,没有synchronize方法
    public static SingletonEHan getInstance(){
        return instance;
    }
}

懒汉模式:我很懒,我不会一开始有把事情做好,只有到马上要用的时候我才回去创建单例。

public class SingletonLanHan{
	
    //懒汉模式(调用的时候才开始加载,也就是new的时机)
    private SingletonLanHan(){
       
    }

    private static SingletonDemo2 instance;

    //因为此时可能多线程同时来创建单例,所以用synchronized关键字
    public static synchronized SingletonLanHan getInstance(){

        if(instance==null){
            instance =  new SingletonLanHan();
        }
        return instance;
    }
}

DCL懒汉模式:正常的懒汉模式效率比较低,应为synchronized关键字放在了方法上边,所以当并发调用时,除了第一个进入方法,其余的都在等待状态,这样比较耗费时间。但是把synchronized关键字加在代码块上,再做一次双重验证就可以大大提升效率。

public class SingletonDCLLanHan{
    //私有化构造方法
    private SingletonDCLLanHan(){}

    private static SingletonDCLLanHan instance;

    public static SingletonDCLLanHan getInstance() {

		//如果单例已经存在,则跳过if块,直接返回;如果单例为空,则创建单例对象
        if(instance==null){
        	//创建过程代码块也是synchronize同步的
            synchronized (SingletonDCLLanHan.class){
                if(instance==null){
                    instance= new SingletonDCLLanHan();
                }
            }
        }
        return instance;
    }
}

静态内部类:具体实现如下

public class SingletonInnerClass {

    private SingletonInnerClass(){}

    private static class InnerClass{
        private static SingletonInnerClass instance= new SingletonInnerClass();
    }

    public static SingletonInnerClass getInstance(){
        return InnerClass.instance;
    }
}

2、之前四种实现方式是因为私有化构造方法,但是反射可以破坏私有,就是通过反射方式构造的对象,可以访问私有变量。代码如下:

public class Reflect{
	
	//通过反射的getDeclaredConstructor方法
	Constructor<SingletonDemo> constructor= SingletonDemo.class.getDeclaredConstructor(null);
    constructor.setAccessible(true);

	//反射方式获取类的对象
	SingletonDemo singletonDemo = constructor.newInstance();

}

3、可以用枚举方法防止反射会破坏单例,也可以用如下方法一定程度上防止反射:

//在构造方法中防止反射
//第一次flag=false,然后设置为true,第二次再来调用构造方法时,会抛出异常
private static boolean flag = false;
private SingletonDemo2 (){
        synchronized (SingletonDemo2.class){
            if(flag==false){
                flag = true;
            } else{
                throw new RuntimeException("不要试图用反射破坏单例模式");
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值