五一放假了,大家是不是因为疫情都减少了出门的频率那?不出门我们就一起在家学习吧!下面就让我们从一个问题出发,开始今天的文章吧。你的类有没有“超生”(到处都是该类的实例)那,它是不是也需要“计划生育”(只需要一个实例)啊?什么你不会?没事让我来告诉你解决类“超生”的办法,使用 单例设计模式 。下面让我们来一起学习一下单例模式。
单例模式是创建类型中常用的一种设计模式。该模式下的类有且仅有一个实例。
1、可以严格控制单例类的使用者怎样以及何时访问唯一的实例。
2、只有一个实例,可以节约系统资源,提高系统的性能,减轻GC的压力。
凡事有利就要弊,单例模式也不可以滥用。
1、单例模式的扩展性很差,因为没有抽象层。
2、单例模式在一定程度上违背了“单一职责原则”。
1、饿汉式
提前创建好类的实例不需要等待创建的时间,直接就可以使用。
/** * 饿汉式(单例模式) */ public class HungrySingleton { // 私有构造方法 private HungrySingleton() { } // 创建一个实例 private static final HungrySingleton HUNGRY_SINGLETON_INSTANCE = new HungrySingleton(); /** * 获取实例的方法 */ public static HungrySingleton getHungrySingleton() { return HUNGRY_SINGLETON_INSTANCE; } } 复制代码
该方式可能在还不需要此实例的时候就已经将创建出来了,没有起到懒加载的效果。
2、使用静态内部类
通过使用静态内部类的方式优化上面的饿汉式,起到懒加载的效果。
/** * 使用静态内部类完成单例模式 */ public class HungrySingleton { // 私有构造方法 private HungrySingleton() { } // 利用静态类的加载时机实现懒加载 private static class InnerHungrySingleton{ private static final HungrySingleton HUNGRY_SINGLETON_INSTANCE = new HungrySingleton(); } /** * 获取实例的方法 */ public static HungrySingleton getHungrySingleton() { return InnerHungrySingleton.HUNGRY_SINGLETON_INSTANCE; } } 复制代码
3、懒汉式
在第一次使用时创建实例,使用时需要考虑线程安全问题。
/** * 懒汉式(单例模式) */ public class LazySingleton { // 私有构造方法 private LazySingleton() { } // 私有静态属性 private static LazySingleton lazySingletonInstance; /** * 获取实例的方法 */ public static LazySingleton getLazySingleton() { // 双重判断 if (null == lazySingletonInstance) { synchronized (LazySingleton.class) { if (null == lazySingletonInstance) { lazySingletonInstance = new LazySingleton(); } } } return lazySingletonInstance; } } 复制代码
该方式起到了懒加载的效果,并且也做了线程安全处理。
4、使用枚举
利用枚举的特性让JVM来保证线程安全问题和单一实例的问题。
/** * 使用枚举实现单例 */ public enum SingletonEnum { INSTANCE; private People people; SingletonEnum(){ people = new People(); } public People getPeople() { return people; } // 定义了一个内部类,为了方便代码展示,也可以是一个独立的类。 class People { } } 复制代码
使用枚举有一个缺点是需要更多的内存空间。