Design pattern ——singleton pattern(单例深入)

Talk is cheap  Show me the code

个人学习笔记--仅供参考

基于上次内容,我们的单例模式已完善,看似没有问题了,也保证了单例对象的唯一性

但是,通过其他非正常手段还是可以改变你单例

1通过反射机制

package pattern;

import java.lang.reflect.Constructor;
/**
 * 
 * @author qsnp236
 *
 */
public class LazyInnerClassSingletonTest {
  public static void main(String[] args) {
	
	try {
		//查你基因信息
		Class<?> clazz= LazySingletonInnerClass.class;
		//复制你的基因信息
		Constructor<?> c = clazz.getDeclaredConstructor();

		//剥夺你的政治权利,后续操作合法化,你不能拒绝
		c.setAccessible(true);
		//用你的基因克隆一个你
		Object o1=c.newInstance();
		//用你的基因再次克隆一个你
		Object o2=c.newInstance();
		System.out.println(o1==o2);
		System.out.println(o1);
		System.out.println(o2);
		System.out.println(o1.hashCode());
		System.out.println(o2.hashCode());
	} catch (NoSuchMethodException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	 catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
}
}

结果:

false
pattern.LazySingletonInnerClass@7852e922
pattern.LazySingletonInnerClass@4e25154f
2018699554
1311053135

需要改造

package pattern;
/**
 * 懒汉式  ,在外部调用getInstance的时候,判断对象是不是空,为空就去床架一个,返回,
 * 这种方式在getInstance 时,如果有多个同时调用,会产生两个对象,
 * 这个是利用内部类
 * @author qsnp236
 *
 */
public  class LazySingletonInnerClass {
    /**
     * 内部初始化函数
     */
	private LazySingletonInnerClass() {
		
		if(InnerClass.innerObj!=null) {
			throw new RuntimeException("不允许创建多个实");
		}
	}

	/**
	 * 提供外部访问,加锁
	 * @return
	 */
	public static final LazySingletonInnerClass getInstance() {
		
		 return InnerClass.innerObj;
	}

	
	
	private static class InnerClass{
		
		public static final LazySingletonInnerClass innerObj =new LazySingletonInnerClass();
	
	}
}

结果

java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at pattern.LazyInnerClassSingletonTest.main(LazyInnerClassSingletonTest.java:21)
Caused by: java.lang.RuntimeException: 不允许创建多个实
	at pattern.LazySingletonInnerClass.<init>(LazySingletonInnerClass.java:16)
	... 5 more

2.通过深度拷贝,序列化和反序列化

package pattern;

import java.io.Serializable;

/**
 * 懒汉式  ,在外部调用getInstance的时候,判断对象是不是空,为空就去床架一个,返回,
 * 这种方式在getInstance 时,如果有多个同时调用,会产生两个对象,
 * 这个是利用内部类
 * @author qsnp236
 *
 */
public  class LazySingletonInnerClass2 implements Serializable{
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;



	/**
     * 内部初始化函数
     */
	private LazySingletonInnerClass2() {
		
		
	}

	/**
	 * 提供外部访问,加锁
	 * @return
	 */
	public static final LazySingletonInnerClass2 getInstance() {
		
		 return InnerClass.innerObj;
	}

	
	
	private static class InnerClass{
		
		public static final LazySingletonInnerClass2 innerObj =new LazySingletonInnerClass2();
	
	}
}

测试:

package pattern;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
/**
 * 
 * @author qsnp236
 * 序列化破坏单例
 *
 */
public class LazyInnerClassSingletonTest3 {
  public static void main(String[] args) {
	
	try {
		LazySingletonInnerClass2 lazySingletonInner1=LazySingletonInnerClass2.getInstance();
		LazySingletonInnerClass2 lazySingletonInner2=null;
		//利用序列化和反序列化产生lazySingletonInner2
		FileOutputStream fos=new FileOutputStream("LazySingletonInnerClass2.obj");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(lazySingletonInner1);
		oos.flush();
		oos.close();
		FileInputStream fis = new FileInputStream("LazySingletonInnerClass2.obj");
		ObjectInputStream ois = new ObjectInputStream(fis);
		lazySingletonInner2 = (LazySingletonInnerClass2)ois.readObject();
		ois.close();
		System.out.println(lazySingletonInner1);
		System.out.println(lazySingletonInner2);
		System.out.println(lazySingletonInner1 == lazySingletonInner2);
	} 
	 catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
}
}

结果

pattern.LazySingletonInnerClass2@3d4eac69
pattern.LazySingletonInnerClass2@776ec8df
false

克隆模式尝试

package pattern;



/**
 * 懒汉式  ,在外部调用getInstance的时候,判断对象是不是空,为空就去床架一个,返回,
 * 这种方式在getInstance 时,如果有多个同时调用,会产生两个对象,
 * 这个是利用内部类
 * @author qsnp236
 *
 */
public  class LazySingletonInnerClass3 implements Cloneable{




	/**
     * 内部初始化函数
     */
	private LazySingletonInnerClass3() {
		
		
	}

	/**
	 * 提供外部访问,加锁
	 * @return
	 */
	public static final LazySingletonInnerClass3 getInstance() {
		
		 return InnerClass.innerObj;
	}

	
	
	private static class InnerClass{
		
		public static final LazySingletonInnerClass3 innerObj =new LazySingletonInnerClass3();
	
	}
	@Override
	public Object clone() throws CloneNotSupportedException
	{
		Object object = super.clone();
		return object;
	}



}

测试

package pattern;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
/**
 * 
 * @author qsnp236
 * 克隆破坏单例
 *
 */
public class LazyInnerClassSingletonTest3 {
  public static void main(String[] args) {
	
	  LazySingletonInnerClass3 l1=LazySingletonInnerClass3.getInstance();
	  try {
		LazySingletonInnerClass3 l2=(LazySingletonInnerClass3) l1.clone();
		System.out.println(l1);
		System.out.println(l2);
		System.out.println(l1 == l2);
	} catch (CloneNotSupportedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
}

结果

pattern.LazySingletonInnerClass3@7852e922
pattern.LazySingletonInnerClass3@4e25154f
false

防止序列化

package pattern;

import java.io.Serializable;

/**
 * 懒汉式 ,在外部调用getInstance的时候,判断对象是不是空,为空就去床架一个,返回, 这种方式在getInstance
 * 时,如果有多个同时调用,会产生两个对象, 这个是利用内部类
 * 
 * @author qsnp236
 *
 */
public class LazySingletonInnerClass4 implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 内部初始化函数
	 */
	private LazySingletonInnerClass4() {

	}

	/**
	 * 提供外部访问,加锁
	 * 
	 * @return
	 */
	public static final LazySingletonInnerClass4 getInstance() {

		return InnerClass.innerObj;
	}

	private static class InnerClass {

		public static final LazySingletonInnerClass4 innerObj = new LazySingletonInnerClass4();

	}

	// 强行阉割,底层调用的时候屏蔽掉新生成的对象
	private Object readResolve() {
		return InnerClass.innerObj;
	}

}

测试类

package pattern;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
/**
 * 
 * @author qsnp236
 *
 */
public class LazyInnerClassSingletonTest4 {
  public static void main(String[] args) {
	
	  try {
			LazySingletonInnerClass4 lazySingletonInner1=LazySingletonInnerClass4.getInstance();
			LazySingletonInnerClass4 lazySingletonInner2=null;
			//利用序列化和反序列化产生lazySingletonInner2
			FileOutputStream fos=new FileOutputStream("LazySingletonInnerClass2.obj");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(lazySingletonInner1);
			oos.flush();
			oos.close();
			FileInputStream fis = new FileInputStream("LazySingletonInnerClass2.obj");
			ObjectInputStream ois = new ObjectInputStream(fis);
			lazySingletonInner2 = (LazySingletonInnerClass4)ois.readObject();
			ois.close();
			System.out.println(lazySingletonInner1);
			System.out.println(lazySingletonInner2);
			System.out.println(lazySingletonInner1 == lazySingletonInner2);
		} 
		 catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
}
}

结果,

pattern.LazySingletonInnerClass4@3d4eac69
pattern.LazySingletonInnerClass4@3d4eac69
true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值