设计模式——单例模式

单例模式

饿汉式

类加载阶段被初始化就会创建实例。提前创建。

class Singleton implements Serializable{
	private Singleton(){
		System.out.println("private Singleton()");
	}
	private static final Singleton INSTANCE=new Singleton();
	public static Singleon getInstance(){
		return INSTANCE;
	}
	public static void otherMethod(){
		System.out.println("otherMethod()");
	}
}

破坏单例情况——反射

void reflection(Class<?> clazz){
	//通过反射获取无参构造函数
	Constructor<?> constructor=clazz.getDeclaredConstructor();
	//有参构造Constructor<?> constructor=clazz.getDeclaredConstructor(String.class,int.class);
	//设置私有构造方法也能使用
	constructor.setAccessible(true);
	System.out.println("反射创建实例:"+constructor.newInstance());
}

预防反射破坏单例——改造构造方法

private Singleton(){
		if(INSTANCE !=null){
			throw new RuntimeException("单例对象已经创建,不能重复创建");
		}
		System.out.println("private Singleton()");
	}

破坏单例情况——反序列化

void serializable(Object instance){
	ByteArrayOutputStream boStream=new ByteArrayOutputStream();
	ObjectOutputStream ooStream=new ObjectOutputStream(boStream);
	//把得到的对象变成字节流。
	ooStream.writeObject(instance);
	//字节流反序列化得到一个新的对象
	ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(boStream.toByteArray()));
	System.out.println("反序列化创建实例:"+ois.readObject());
}

预防反序列化破坏单例——添加特殊方法readResolve()

public Object readResolve(){
	return INSTANCE;
}

破坏单例情况——Unsafe

void unsafe(Class<?> clazz){
	Object o=UnsafeUtils.getUnsafe().allocateInstance(clazz);
	System.out.println("Unsafe创建实例:"+o);
}

枚举饿汉式

预防 反射、反序列化破坏单例模式。

enum Singleton{
	INSTANCE;

	private Singleton(){}
		System.out.println("private Singleton()");
	}
	
	public static Singleon getInstance(){
		return INSRANCE;
	}
	public static void otherMethod(){
		System.out.println("otherMethod()");
	}
	//重写toString方法
	String toString(){return getClass().getName+"@"+Integer.toHecString(hashCode());}
}
//枚举编译后enum xxx--->class xxx extends Enum<xxx>
class Singleton extends Enum<Singleton>{
	public static final Singleton INSTANCE;
	//名字,序号0开始
	private Singleton(String name,int ordinal){
		super(name,ordinal);
	}
	//静态代码块,类加载时执行
	static{
		INSTANCE=new Singleton("INSTANCE",0);
	}
}

破坏单例情况——Unsafe

void unsafe(Class<?> clazz){
	Object o=UnsafeUtils.getUnsafe().allocateInstance(clazz);
	System.out.println("Unsafe创建实例:"+o);
}

通过Unsafe造出一个Enum对象

public class CreateEnum {
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);

        Unsafe unsafe= (Unsafe) unsafeField.get(null);
        //获取字段偏移量(储存单元的实际地址与其所在的段地址之间的距离)
        //objectFieldOffset获取非静态属性Field在对象实例中的偏移量
        //staticFieldOffset获取静态属性Field在对象实例中的偏移量
        long nameOffset = unsafe.objectFieldOffset(Enum.class.getDeclaredField("name"));
        long ordinalOffset = unsafe.objectFieldOffset(Enum.class.getDeclaredField("ordinal"));
        //用于创建一个类的实例,不会调用这个实例的构造方法
        Sex o= (Sex) unsafe.allocateInstance(Sex.class);
        //CAS 操作 给新对象赋值 (对象,字段偏移量,原始值,更新值)
        unsafe.compareAndSwapObject(o,nameOffset,null,"犹太人");
        unsafe.compareAndSwapInt(o,ordinalOffset,0,2);
        System.out.println(o.name());
        System.out.println(o.ordinal());
        Sex o1=Sex.MAN;
        System.out.println(o1.name());
        System.out.println(o1.ordinal());
    }

    enum Sex{
        MAN;
    }
}

懒汉式DCL(Double Check Lock)

class Singleton implements Serializable{
	private Singleton(){
		System.out.println("private Singleton()");
	}
	//类加载时不创建对象
	//volatile 保证可见性,有序性(避免指令重排导致 赋值操作提前 )
	private static volatile Singleton INSTANCE=null;
	//等调用时再创建对象
	public static Singleon getInstance(){
		if(INSTANCE==null){
			synchronized (Singleton.class){
				if(INSTANCE==null){
					INSTANCE=new Singleton();
				}
			}
		}
		return INSTANCE;
	}
	public static void otherMethod(){
		System.out.println("otherMethod()");
	}
}

懒汉式——内部类

class Singleton implements Serializable{
	private Singleton(){
		System.out.println("private Singleton()");
	}
	//内部类
	private static class Holder{
		static Singleton INSTANCE=new Singleton();
	}
	//等调用时再创建对象
	public static Singleon getInstance(){
		return Holder.INSTANCE;
	}
	public static void otherMethod(){
		System.out.println("otherMethod()");
	}
}

JDK中单例模式

Runtime 饿汉式单例

在这里插入图片描述

System 懒汉式DCL(双检锁)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值