设计模式之单例模式

1. 单例模式介绍

单例模式属于创建型模式。

1.1 应用场景

保证系统启动到终止一个类仅有一个实例,实现资源共享,并提供一个访问实例的全局访问点。
Spring中的Bean默认就是单例的,而BeanFactory则是全局访问点。

1.2 单例模式实现案例
  1. 日历
  2. IOC容器
  3. 配置文件
1.3 常用写法
  1. 饿汉式
  2. 懒汉式
  3. 注册登记式
  4. 枚举式
2. 单例模式实现
2.1 饿汉式

线程安全
优点: 效率高
缺点: 不适用也会占用空间

public class Single {

    private Single(){}

    private static final Single single = new Single();

    public static Single getInstance(){
        return single;
    }

}
2.2 饿汉式

线程不安全

public class LazySingle {

    private LazySingle(){}

    private static LazySingle lazy = null;

    public static LazySingle getInstance(){
        if(lazy == null){
            lazy = new LazySingle();
        }
        return lazy;
    }
}

要想线程安全在getInstance方法中加上synchronized即可,不过这样子做性能很差。可以使用内部类方式。

线程安全

//默认使用LazySingle的时候,会先初始化内部类,如果没使用的话,内部类不加载
public class LazySingle {
	private boolean flag = false;
    private LazySingle(){
    	//防止反射侵入创建实例
 		synchronized (LazySingle.class){
            if(flag == false){
                flag = !flag;
            }else{
                throw new RuntimeException("单例已被侵犯");
            }
        }
	}
    public static LazySingle getInstance(){
        return LazyInstance.LAZY;
    }
       //默认不加载
    private static class LazyInstance{
        private static final LazySingle LAZY = new LazySingle();
    }
}
2.3 注册登记式

线程不安全

//Spring中的就是用这种注册式单例
public class BeanFactory {

    private BeanFactory(){}
    
    private static Map<String,Object> ioc = new ConcurrentHashMap<String,Object>();

    public static Object getBean(String className){

        if(!ioc.containsKey(className)){
            Object obj = null;
            try {
                obj = Class.forName(className).newInstance();
                ioc.put(className,obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return obj;
        }else{
            return ioc.get(className);
        }

    }
}
2.4 枚举式

枚举本身就是初始化好的实例,所以是绝对安全的单例。

public enum Single {  
    INSTANCE(){
		private int age;
	};
}
3. 注意

需要注意的是单例模式在序列化和反序列化过程中,单例会遭到破坏。
因为序列化就是把内存中的状态通过转换成字节码的形式,从而转换一个IO流,写入到特定地方(磁盘、网络IO)。
反序列化就是将已经持久化的字节码内容,转换为IO流通过IO流的读取,将读取的内容转换为Java对象,在转换过程中会重新创建对象。
解决方案:重写readResolve()即可。
设计模式是程序员内功之一,切记不要死记硬背,用心理解。下篇将介绍原型模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值