从未这么明白的设计模式(一):单例模式

单例模式是一种常用的软件设计模式,用于保证一个类只有一个实例,并提供全局访问点。本文详细介绍了单例模式的原理、应用场景、实现方法,包括枚举实现、私有构造器的饿汉式和饱汉式,以及线程安全的双重检查锁。通过源码分析,揭示了枚举实现单例的不可破坏性。同时,文章探讨了单例模式在资源管理和多线程环境中的价值。
摘要由CSDN通过智能技术生成

cover

什么是单例?为什么要用单例?

一个类被设计出来,就代表它表示具有某种行为(方法),属性(成员变量),而一般情况下,当我们想使用这个类时,会使用new关键字,这时候jvm会帮我们构造一个该类的实例。而我们知道,对于new这个关键字以及该实例,相对而言是比较耗费资源的。所以如果我们能够想办法在jvm启动时就new好,或者在某一次实例new好以后,以后不再需要这样的动作,就能够节省很多资源了。

哪些类可以使用单例?

一般而言,我们总是希望无状态的类能够设计成单例,那这个无状态代表什么呢? 简单而言,对于同一个实例,如果多个线程同时使用,并且不使用额外的线程同步手段,不会出现线程同步的问题,我们就可以认为是无状态的,再简单点:一个类没有成员变量,或者它的成员变量也是无状态的,我们就可以考虑设计成单例。

实现方法

好了,我们已经知道什么是单例,为什么要使用单例了,那我们接下来继续讨论下怎么实现单例。
一般来说,我们可以把单例分为行为上的单例管理上的单例行为上的单例代表不管如何操作(此处不谈cloneable,反射),至始至终jvm中都只有一个类的实例,而管理上的单例则可以理解为:不管谁去使用这个类,都要守一定的规矩,比方说,我们使用某个类,只能从指定的地方’去拿‘,这样拿到就是同一个类了。
而对于管理上的单例,相信大家最为熟悉的就是spring了,spring将所有的类放到一个容器中,以后使用该类都从该容器去取,这样就保证了单例。
所以这里我们剩下的就是接着来谈谈如何实现行为上的单例了。一般来说,这种单例实现有两种思路,私有构造器,枚举

枚举实现单例

枚举实现单例是最为推荐的一种方法,因为就算通过序列化,反射等也没办法破坏单例性,例子:

public enum SingletonEnum {
   
    INSTANCE;

    public static void main(String[] args) {
   
        System.out.println(SingletonEnum.INSTANCE == SingletonEnum.INSTANCE);
    }
}

结果自然是true,而如果我们尝试使用反射破坏单例性:

public enum BadSingletonEnum {
   
    /**
     *
     */
    INSTANCE;

    public static void main(String[] args) throws Exception{
   
        System.out.println(BadSingletonEnum.INSTANCE == BadSingletonEnum.INSTANCE);

        Constructor<BadSingletonEnum> badSingletonEnumConstructor = BadSingletonEnum.class.getDeclaredConstructor();
        badSingletonEnumConstructor.setAccessible(true);
        BadSingletonEnum badSingletonEnum = badSingletonEnumConstructor.newInstance();

        System.out.println(BadSingletonEnum.INSTANCE == badSingletonEnum);
    }
}

结果如下:

Exception in thread "main" java.lang.NoSuchMethodException: cn.jsbintask.BadSingletonEnum.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at cn.jsbintask.BadSingletonEnum
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值