单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例

单例模式:单例模式是什么有啥用什么时候用为什么要用?怎样用?先来一波素质五连

是什么?

单例模式?字面上理解,单:一个,例:实例,也就是我们所说的对象

有啥用?

是为了资源的重复利用,只需要赋值或者初始化一次,大家就都能重复使用

什么时候用?为什么要用?(只有一份的如日历,只需要一份的如IOC容器)

Listener 监听器,Calender 日历类,IOC容器类,配置信息Config(一搬是单例)这些都是单例的

怎样用?(这个一句话说不了,容我细细道来)

下面我将用饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式反序列化如何保证单例 单例模式的运用形式进行详细说明

 

  1. 饿汉式(有处明显错误导致无法实现单例,答案暗藏在后文中)

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第1张图片

什么叫饿汉式?我的理解就是,饿了就迫不及待想吃,看下面第9行代码,声明为

private static final:说明类加载时就初始化就初始化对象,然后静态的,所以对象一直保存,直到程序停止

缺点:自然就是无论你用不用这个对象,在加载这个类的时候他都给你初始化了,都会占用空间,直到程序停止

优点:很明显,因为它在类被加载时就初始化,所以不存在对象创建时的并发问题,也就是不存在线程安全问题,可以保证单例,而且效率也算不错,因为当创建对象时需要的那几纳秒省了

建议应用场景:如果某个类的对象只需要一份,并且使用非常频繁,可以使用这种模式

 

  1. 懒汉式(明说了,答案就在下图)

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第2张图片

什么是懒汉式?我的理解就是,懒人特点了解下,什么事情都不急着提前准备,需要用时才去准备

我们可以看到,懒汉模式下的对象,我们可以在需要时再调用方法得到,并且能保证单例(能保证?)下面就来在优缺点里继续分析

优点:避免了内存的浪费,需要对象时才获得,而且非高并发时基本能保证单例

缺点:很明显,上面都说了非高并发时能保证单例,那么高并发时不能保证一定单例, 怎样解决呢,在方法前面加个synchronized关键字(如果对性能要求不高的话可加,毕竟同步锁要等待,不懂的可以去了解下同步锁synchronized)

  1. 既然上面或多或少都有缺点,下面再来个懒汉式改进版(也就是标题的最牛逼版,请不要叫我标题档...)单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第3张图片

优点:兼顾了饿汉模式的内存占用问题与synchronized的性能问题(性能我有测试,创建200W个对象速度跟饿汉模式基本没区别),测试代码就不贴了,自己动手试试

缺点:欢迎留言

  1. 枚举类型

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第4张图片

enum类型只加载一次所以单例

  1. 注册登记式

简单模拟spring中ioc容器(用于存放与管理对象)

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第5张图片

只列举了取对象时的部分代码,并且没有考虑线程安全问题,有兴趣的可以下载spring源码去瞧瞧,代码简单就不多解释

6.如何保证序列化前与反序列化后对象一致

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第6张图片

如下可以看到我测试类中,序列化前与反序列化后两个对象不一样

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第7张图片

那么,如何保证序列化前与反序列化后对象相等呢?

加入如下方法

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第8张图片

然后同样代码进行测试

单例模式之饿汉式,懒汉式,最牛逼单例模式,枚举,注册登记式及反序列化如何保证单例_第9张图片

其实也就是深复制浅复制的区别,不懂深复制浅复制的请看后面 原型模式 那篇

如果能看到这里也是真不容易了,老铁

欢迎提问,欢迎纠错,可以转载,但请注明本文链接

你可能感兴趣的:(常用设计模式)