欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 设计模式简述(二)单例模式

设计模式简述(二)单例模式

2025/4/9 5:09:16 来源:https://blog.csdn.net/tergou/article/details/147015163  浏览:    关键词:设计模式简述(二)单例模式

单例模式

  • 描述
  • 基本使用
    • 防破坏单例
    • 饿汉式
    • 懒汉式
    • 有上限多例

描述

一个类全局只有一个实例,自行实例化并提供给使用。
构造函数私有化是前提

基本使用

防破坏单例

  • 防反射:在构造函数中判断类中实例是否已初始化
private InnerClassSingleton (){if(InnerClassSingletonHolder.instance != null){throw new RuntimeException("单例模式 不允许 多例存在");}
}
  • 防克隆:单例类不要实现Cloneable接口或者强制覆盖clone方法
    如果采用的是强制覆盖clone方法,可以返回单例对象或者 直接报错
  • 防序列化:对象反序列化会调用对象的readResolve方法,可以在类中声明这个方法,并返回单例对象
    Object readResolve() throws ObjectStreamException{return InnerClassSingletonHolder.instance;}

饿汉式

  • 静态成员初始化
public class HungrySingleton {private static HungrySingleton instange = new HungrySingleton();private HungrySingleton() {if (instange != null) {throw new RuntimeException("单例模式不允许 多例存在");}}public static HungrySingleton getInstance() {return instange;}
}
  • 静态代码块初始化
public class HungrySingleton {private static HungrySingleton instange;static {instange = new HungrySingleton();}private HungrySingleton() {if (instange != null) {throw new RuntimeException("单例模式不允许 多例存在");}}public static HungrySingleton getInstance() {return instange;}
}
  • 枚举(直接用吧JVM层面保证单例)
/*** @author sdaf* <p>* 枚举:本质也是一个类,底层是一个实现 Eunm 的一个类,编译器会默认添加一些属性及方法* 枚举站在单例实现角度上看 就是一个饿汉模式实现*/
public enum EnumSingleton {INSTANGE;public void test(){// code}
}

懒汉式

  • synchronized + double check
public class LazySingleton {private static volatile LazySingleton lazySingleton;private LazySingleton() {if(lazySingleton!=null){throw new RuntimeException("单例模式不允许 多例存在");}}public static LazySingleton getInstance() {if (lazySingleton == null) {// 线程A 线程B 均进入非空判断逻辑// 线程A 先行添加锁,然后创建实例对象,并返回// 此时线程B已经 进入非空的逻辑,然后依然会去加锁,然后创建对象,此时就违背了单例对象定义// 所以需要在加锁的内部再次进行非空判断,保证对象单例synchronized (LazySingleton.class) {if (lazySingleton == null) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}lazySingleton = new LazySingleton();// new 一个对象步骤进一步解析// 1、在堆内存开辟一块空间// 2、初始化对象(创建对象)// 3、将开辟的内存空间地址赋值给变量// 【但是】由于编译器和CPU的指令重排可能导致 2 和 3 执行顺序发生改变// 为 1 3 2// 此时如果第二个线程 在 第一个线程执行到 3 与 2之间时 进来// instance 是有值的,因为 instance 拿到的只是 内存地址而已,并不知道这个地址上是否实在的对象// 只有当这个对象完成初始化(创建)后这个地址上才有具体的值// 此时第二个线程拿到地址就会直接返回这个引用,// 但是此时这个对象是个 null , 可能会引起 NullPointerException// 为了防止 整个 new 操作被执行重排 需要使用关键字 volatile 来修饰变量}}}return lazySingleton;}
  • 静态内部类
/*** @author sdaf* @Description 基于静态内部类的单例模式,也是一种懒加载* 也是借助于JVM类加载机制实现的线程安全* 类加载顺序:* 1.加载类的Class文件到内存中* 2.连接JVM,验证Class合法性,静态成员赋默认值,解析处理后的数据* 3.给静态成员赋值* 静态内部类只有在使用这个类的时候才会去加载这个类*/
public class InnerClassSingleton implements Serializable{private static final long serialVersionUID = -790330830636259886L;private static class InnerClassSingletonHolder{private static InnerClassSingleton instance= new InnerClassSingleton();}private InnerClassSingleton (){if(InnerClassSingletonHolder.instance != null){throw new RuntimeException("单例模式 不允许 多例存在");}}public static InnerClassSingleton getInstance(){return InnerClassSingletonHolder.instance;}
//Object readResolve() throws ObjectStreamException{return InnerClassSingletonHolder.instance;}
}

有上限多例

单例模式可以扩展为有上限多例

public class Multiton {private Multiton() {}private static final int MAX_INSTANCES = 3;private static final List<Multiton> instances = new ArrayList<>();// 饿汉式初始化static {for (int i = 0; i < MAX_INSTANCES; i++) {instances.add(new Multiton());}}// 懒汉式初始化public static Multiton getInstanceLazy(int index) {if (instances.get(index) == null) {synchronized (Multiton.class) {if (instances.get(index) == null) {instances.set(index, new Multiton());}}}return instances.get(index);}// 随机获取public static Multiton getRandomInstance() {Random random = new Random();return instances.get(random.nextInt(MAX_INSTANCES));}// 指定获取public static Multiton getInstance(int index) {if (index < 0 || index >= MAX_INSTANCES) {throw new IllegalArgumentException("索引超出范围");}return instances.get(index);}// 业务方法public void test() {}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com