1.什么是单例模式
单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例),就好比有一口井,只需要一个桶就可以打水上来了,不需要额外的桶来进行打水操作。这就是单例模式
2.单例模式有哪些设计方式
单例模式,主流的设计方式有两种,一种是懒汉,另一种是饿汉。其中懒汉模式,顾名思义,就是比较懒在代码初始化的时候就生成一个唯一实例给你,就像我们去井李打水,懒汉模式就是比较懒,井建好的时候,需要打水的时候采取买一个桶去打水。饿汉模式,就如其名,很饿了,狠不得立马去吃饭那种,就像井建好了以后,立马买一个桶,不管有没有打水的需求。所以我们根据这些特点,来写代码
1.懒汉模式
package cn.com.lovefy.demo;
/**
* @author lyf
*/
public class LazyOneDemo {
private static volatile LazyOneDemo lazyOneDemo;
//不允许对象被实例化
private LazyOneDemo(){
}
/**
* 获取实例
* @return {@link LazyOneDemo}
*/
public static LazyOneDemo getInstance() {
if(lazyOneDemo!=null){
synchronized (LazyOneDemo.class){
if(lazyOneDemo!=null) {
lazyOneDemo = new LazyOneDemo();
}
}
}
return lazyOneDemo;
}
}
特点:延时加载,只有在正在需要的时候才开始实例化。
1、线程安全问题
2、双重判断double check,加锁优化(锁也可以直接加锁到方法上,但是会耗费性能)
3、使用volatile关键字,防止指令重排序
2.饿汉模式
package cn.com.lovefy.demo;
/**
* @author lyf
*/
public class HunglyOneDemo {
private static HunglyOneDemo hunglyOneDemo = new HunglyOneDemo();
//不允许对象被实例化
private HunglyOneDemo(){
}
/**
* 获取实例
* @return {@link HunglyOneDemo}
*/
public static HunglyOneDemo getInstance() {
return hunglyOneDemo;
}
}
特点:类加载的初始化阶段就完成了实例的初始化,本质上是借助于jvm的类加载机制,保证实例的唯一性。(急加载)
类加载机制:
1、加载:加载二进制文件到内存中,并生成对应的class数据结构
2、连接:包括验证、准备(给静态变量赋默认值,引用类型为null,int为0,boolean为false等等)、解析(将符号应用替换为直接引用)
3、初始化(执行静态代码块、给静态变量赋初值)
注意:如果当前类的父类没有被加载,则会先加载父类
3.其他单例的实现
1.内部静态类的实现
class InnerOneDemo {
private static class InnerOneDemoHolder {
private static InnerOneDemo innerOneDemo= new InnerOneDemo();
}
//不允许被实例化
private InnerOneDemo(){
}
/**
* 获取实例
* @return {@link InnerOneDemo}
*/
public static InnerOneDemo getInstance() {
return InnerOneDemoHolder.innerOneDemo;
}
}
特点:也是借助jvm的类加载机制,保证实例的唯一性(懒加载)
当访问instance时才会初始化实例
缺点:可以通过反射进行破坏
2.枚举的形式实现
package com.demo.Enum;
/**
* @BelongsProject: demo
* @BelongsPackage: com.demo.Enum
* @Author: liyifan
* @CreateTime: 2023-02-13 09:56
* @Description: 枚举单例模式
*/
public enum OneEnum {
ONE;
public static OneEnum getInstance(){
return ONE;
}
}
特点:简单,线程安全,也能够防护反射攻击(禁止反射实例化enum类型类)。
网友评论