23种设计模式——单例模式

23种设计模式——单例模式

一、实现方式

1、懒汉模式

class LazySingleton{
    private static volatile LazySingleton instance;//volatile关键字防止指令重排序
    private LazySingleton(){};//构造方法私有化,防止new对象
    public static LazySingleton getInstance(){
        if(null==instance){
            synchronized (LazySingleton.class){
                if(null==instance){
                    instance=new LazySingleton();
                }
            }
        }
        return instance;
    }
}

2、饿汉模式

只有在主动使用对应的类时,才会触发初始化,如(当前类时启动类即main函数所在类,直接new操作,访问静态属性、访问静态方法的子类等)

class HungrySingleton{
    private static HungrySingleton instance=new HungrySingleton();//初始化的时候是线程安全的
    private HungrySingleton(){};
    
    public static HungrySingleton getInstance(){
        
        return instance;
    }
}

3、静态内部类

当调用getInstance时才会进行类的初始化

class InnerClassSingleton{
    private static class SingletonHolder{
        private static InnerClassSingleton instance=new InnerClassSingleton();
        
    }
    private InnerClassSingleton(){};
    
    public static InnerClassSingleton getInstance(){
        
        return SingletonHolder.instance;
    }
    
}
1)补充

用以上方式实现单例,当利用反射来创建对象时,获得的是并不是同一个实例,如下(以饿汉模式为例)

public class SingletonTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor<HungrySingleton> declaredConstructor = HungrySingleton.class.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        HungrySingleton hungrySingleton = declaredConstructor.newInstance();

        HungrySingleton instance=HungrySingleton.getInstance();
        System.out.println(instance==hungrySingleton);

    }
}

输出如下

image-20220601013414515

输出false,得以证明通过反射获得的不是同一个实例

2)规避方式

在构造函数处加一个判断,不为空时则抛出异常

private HungrySingleton(){
        if(instance!=null){
            throw new RuntimeException("单例不允许多个实例");
        }
    };

如下:

image-20220601013759861

4 、枚举方式

当使用枚举类型时,则不能使用反射创建实例,也可以规避上面问题,实现如下:

enum EnumSingleton{
    INSTANCE;
    
}
public class SingletonTest {
    public static void main(String[] args)  {
        EnumSingleton instance1 = EnumSingleton.INSTANCE;
        EnumSingleton instance2 = EnumSingleton.INSTANCE;
        System.out.println(instance1==instance2);
    }
}

输出如下:

image-20220601020118144

未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值