每个程序员都会说的单例模式

为什么单例模式经常会被在面试中问到?

答案很简单单例模式是23种设计模式中最容易使用代码实现的。

你能想到的实现方法有哪些呢?

1、饿汉式

/**
 * @author 冷,静
 *	为什么称之为饿汉式呢?
 *	那是因为对象随着类的加载就已经创建了,有点迫不及待的样子
 */
public class Single1 {
	//1、构造方法私有化
	private Single1() {}
	//2、创建对象
	private static Single1 single = new Single1();
	//3、对外提供公共的访问方法
	public static Single1 getInstance() {
		return single;
	}
}

2、懒汉式

public class Single1 {
	//1、构造方法私有化
	private Single1() {}
	//2、创建对象
	private static Single1 single = null;
	//3、对外提供公共的访问方法
	public static Single1 getInstance() {
		if (single == null) {
			single = new Single1();
		}
		return single;
	}
}

但是这两种方法都有各自的弊端

首先懒汉式存在线程同步的问题,比如说A线程和B线程同时判断single是否为null,A线程先进入,但是还没有创建对象,那么此时single还是为null,那么B线程也进入判断体准备创建对象,此时A线程已经创建Single对象,紧接着B线程也创建了Single对象,那么单例模式就被打破了。

接下来改进一下

改进版懒汉式单例模式

public class Single{
	private static Single single = null;
	private Single(){}
	public static Single getInstance() {
	if (single == null) {
		synchronized (Single.class) {
			if (single == null) {
				single = new Single();
			}
		}
	}
	return single;
	}
}

改进的方式增加了双重校验锁,避免了线程同步的问题,但是不管如何改进,只要第一步是构造方法私有化,都无法真正的实现单例模式,因为我可以通过反射来调用私有的构造方法创建对象,这就打破了单例模式。

反射打破单例:

public void test13() {
		try {
			for (int i = 1; i < 10; i++) {
				Class clazz = Class.forName("domain.Single");
				Constructor constructor = clazz.getDeclaredConstructor();
				constructor.setAccessible(true);
				System.out.println(constructor.newInstance());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

3、静态内部类

public class Single{
	private Single(){}
	private static class Instance{
		private static Single single = new Single();
	}
	private static Single getInstance() {
		return Instance.single;
	}
}
静态内部类随着类的加载而加载,并且只加载一次,所以他是单例的。

那么怎样才能实现真正的单例模式呢??

下篇文章将会详细介绍。

猜你喜欢

转载自blog.csdn.net/leng1235/article/details/80937949