单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
代码
懒汉
public class SPUtils {
private static SPUtils spUtils = null;
private SPUtils() {
}
public static SPUtils getInstant() {
if (spUtils == null) {
spUtils = new SPUtils();
}
return spUtils;
}
}
- 懒汉上扩展出较多变种,说明我们在日常工作中性能还是很重要的,尤其是移动端开发
在开发中一切简单的东西在加入多线程并发后问题就会变得复杂,直接加锁,这种也是使用很少的
public class SPUtils {
private static SPUtils spUtils = null;
private SPUtils() {
}
public static synchronized SPUtils getInstant() {
if (spUtils == null) {
spUtils = new SPUtils();
}
return spUtils;
}
}
再来一种,锁加在判断为空之后,好处就是不用每次都判断
public class SPUtils {
private static SPUtils spUtils = null;
private SPUtils() {
}
public static SPUtils getInstant() {
if (spUtils == null) {
synchronized (SPUtils.class) {
if (spUtils == null) {
spUtils = new SPUtils();
}
}
}
return spUtils;
}
}
饿汉
public class SPUtils {
private static SPUtils spUtils = new SPUtils();
private SPUtils() {
}
public static SPUtils getInstant() {
return spUtils;
}
}
最后来比较流行的写法
public class SPUtils {
private static SPUtils spUtils = null;
private SPUtils() {
}
public static SPUtils getInstant() {
return LayzSPutils.spUtils;
}
private static class LayzSPutils {
private static final SPUtils spUtils = new SPUtils();
}
}
这里就要讲到static的相关知识了,static的初始化优先级较普通类高,比如同样的代码块加载的时机比普通代码块早,字段同样如此,static还有一个特点就是在第一次初始化的生活会加锁,以后的使用就是一个普通的引用了。
但是还是会因为Clone或者反射初始化对象
反射
public class ElvisModified
{
private static boolean flag = false;
private ElvisModified(){
synchronized(ElvisModified.class)
{
if(flag == false)
{
flag = !flag;
}
else
{
throw new RuntimeException("单例模式被侵犯!");
}
}
}
其实在effective java中推荐使用枚举类型,可是苦于Google不推荐使用Enum类型,而序列化则使用transient关键字