单例模式:单例模式是什么?有啥用?什么时候用?为什么要用?怎样用?(先来一波素质五连)
是什么?
单例模式?字面上理解,单:一个,例:实例,也就是我们所说的对象
有啥用?
是为了资源的重复利用,只需要赋值或者初始化一次,大家就都能重复使用
什么时候用?为什么要用?(只有一份的如日历,只需要一份的如IOC容器)
Listener 监听器,Calender 日历类,IOC容器类,配置信息Config(一搬是单例)这些都是单例的
怎样用?(这个一句话说不了,容我细细道来)
下面我将用饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式,反序列化如何保证单例 等单例模式的运用形式进行详细说明
- 饿汉式(有处明显错误导致无法实现单例,答案暗藏在后文中)
什么叫饿汉式?我的理解就是,饿了就迫不及待想吃,看下面第9行代码,声明为
private static final:说明类加载时就初始化就初始化对象,然后静态的,所以对象一直保存,直到程序停止
缺点:自然就是无论你用不用这个对象,在加载这个类的时候他都给你初始化了,都会占用空间,直到程序停止
优点:很明显,因为它在类被加载时就初始化,所以不存在对象创建时的并发问题,也就是不存在线程安全问题,可以保证单例,而且效率也算不错,因为当创建对象时需要的那几纳秒省了
建议应用场景:如果某个类的对象只需要一份,并且使用非常频繁,可以使用这种模式
- 懒汉式(明说了,答案就在下图)
什么是懒汉式?我的理解就是,懒人特点了解下,什么事情都不急着提前准备,需要用时才去准备
我们可以看到,懒汉模式下的对象,我们可以在需要时再调用方法得到,并且能保证单例(能保证?)下面就来在优缺点里继续分析
优点:避免了内存的浪费,需要对象时才获得,而且非高并发时基本能保证单例
缺点:很明显,上面都说了非高并发时能保证单例,那么高并发时不能保证一定单例, 怎样解决呢,在方法前面加个synchronized关键字(如果对性能要求不高的话可加,毕竟同步锁要等待,不懂的可以去了解下同步锁synchronized)
- 既然上面或多或少都有缺点,下面再来个懒汉式改进版(也就是标题的最牛逼版,请不要叫我标题档...)
优点:兼顾了饿汉模式的内存占用问题与synchronized的性能问题(性能我有测试,创建200W个对象速度跟饿汉模式基本没区别),测试代码就不贴了,自己动手试试
缺点:欢迎留言
- 枚举类型
enum类型只加载一次所以单例
- 注册登记式
简单模拟spring中ioc容器(用于存放与管理对象)
只列举了取对象时的部分代码,并且没有考虑线程安全问题,有兴趣的可以下载spring源码去瞧瞧,代码简单就不多解释
6.如何保证序列化前与反序列化后对象一致
如下可以看到我测试类中,序列化前与反序列化后两个对象不一样
那么,如何保证序列化前与反序列化后对象相等呢?
加入如下方法
然后同样代码进行测试
其实也就是深复制浅复制的区别,不懂深复制浅复制的请看后面 原型模式 那篇
如果能看到这里也是真不容易了,老铁
欢迎提问,欢迎纠错,可以转载,但请注明本文链接