注(1): 本文来源:
黑马程序员Java设计模式详解, 23种Java设计模式(图解+框架源码分析+实战)
注(2):本文描述只是粗略描述:方便记忆,如需更加详细讲解:推荐从零开始学习Java设计模式
1. 饿汉式
(1)静态成员变量的方式
/**
* 饿汉式单例模式==>静态成员变量方式
* @author hzy
* @since 2022/10/7
*
*/
public class Singleton01 {
private String name;
//私有构造方法
private Singleton01(){};
//在本类中创建对象
private static final Singleton01 instance = new Singleton01();
//提供公共的访问方式给外界访问
public static Singleton01 getInstance(){
return instance;
}
public String getName() {
return name;
}
public Singleton01 setName(String name) {
this.name = name;
return this;
}
}
(2)静态块的方式
/**
* 饿汉式单例模式==>静态块的方式
* @author hzy
* @since 2022/10/7
*/
public class Singleton02 {
private String name;
//私有构造方法
private Singleton02(){};
private static final Singleton02 instance;
//在静态代码块中赋值
static {
instance = new Singleton02();
}
public static Singleton02 getInstance(){
return instance;
}
public String getName() {
return name;
}
public Singleton02 setName(String name) {
this.name = name;
return this;
}
}
2. 懒汉式
(1)双重检查锁、指令重排
/**
* 懒汉单例模式
* @author hzy
* @since 2022/10/7
*/
public class LazySingleton04 {
private String name;
//私有的构造方法
private LazySingleton04() {};
//使用volatile关键字,解决指令重排问题
private static volatile LazySingleton04 instance;
//对外提供访问方式: 加锁,两次检查解决线程安全问题
public static LazySingleton04 getInstance(){
if ( instance==null){
synchronized (LazySingleton04.class){
if (instance==null){
instance = new LazySingleton04();
}
}
}
return instance;
}
public String getName() {
return name;
}
public LazySingleton04 setName(String name) {
this.name = name;
return this;
}
}
使用
Singleton04 instance = LazySingleton04.getInstance();
(2)枚举方式
/**
* 懒汉单例模式==>枚举方式创建单例对象
* @author hzy
* @since 2022/10/7
*/
public enum LazySingleton06 {
INSTANCE;
}
(3)静态内部类的方式
/**
* 懒汉单例模式==>线程安全: 静态内部类的方式创建
* @author hzy
* @since 2022/10/7
*/
public class LazySingleton05 {
private String name;
private LazySingleton05() {};
private static class LazySingletonHolder{
private static final LazySingleton05 INSTANCE = new LazySingleton05();
}
public LazySingleton05 getInstance(){
return LazySingletonHolder.INSTANCE;
}
public String getName() {
return name;
}
public LazySingleton05 setName(String name) {
this.name = name;
return this;
}
}
3. 防止单例模式被破坏
(1)防止序列化和反序列化破坏
破坏示例
/**
* 单例模式破坏: 序列化的方式破坏
* @author hzy
* @since 2022/10/7
*/
public class SingletonSerializeDamage {
public static void main(String[] args) throws Exception {
// saveObjectToFile();
//此时我们两次调用方法,返回的对象不是同一个
getFileObject();
getFileObject();
}
private static void saveObjectToFile() throws Exception{
Singleton instance = Singleton.getInstance();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\single\\single.txt"));
oos.writeObject(instance);
oos.close();
}
private static void getFileObject() throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\single\\single.txt"));
Singleton singleton =(Singleton) objectInputStream.readObject();
System.out.println(singleton);
}
}
解决:
在该类中添加readResolve()方法
/**
* @author hzy
* @since 2022/10/7
*/
public class Singleton implements Serializable {
private Singleton(){
};
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
//加上该方法,在反序列化时,会检查该方法存在性,如果存在,返回该方法的返回值,不存在则创建新对象
public Object readResolve(){
return SingletonHolder.INSTANCE;
}
}
再次执行示例时,两次返回的对象为同一个
(2)反射破坏
破坏示例
/**
* 单例模式破坏: 反射的方式破坏
* @author hzy
* @since 2022/10/7
*/
public class ReflectionDamage {
public static void main(String[] args) throws Exception {
//获取字节码对象
Class<Singleton> singletonClass = Singleton.class;
//获取无参构造方法
Constructor<Singleton> declaredConstructor = singletonClass.getDeclaredConstructor();
//修改构造方法访问权限(因为构造方法是私有的)
//取消访问检查
declaredConstructor.setAccessible(true);
//创建对象
Singleton singleton = declaredConstructor.newInstance();
Singleton singleton1 = declaredConstructor.newInstance();
System.out.println(singleton1==singleton);
}
}
解决:
在该类的构造方法中加锁,且加判断,是否为第一次创建对象,如果是,则创建新对象,如果不是,则抛出异常
package com.synda.design.patterns.single.damage.reflectionmodel;
import java.io.Serializable;
/**
* @author hzy
* @since 2022/10/7
*/
public class Singleton implements Serializable {
private static boolean flag = false;
private Singleton(){
synchronized (Singleton.class){
//如果flag是true,则不是第一次创建对象,直接抛出异常
if (flag){
throw new RuntimeException("The object exists ");
}
flag = true;
}
}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
public Object readResolve(){
return SingletonHolder.INSTANCE;
}
}