单例模式

  • 前言
  • 一、单例模式特点
    • 二、单例模式的优点
    • 三、单例模式的缺点
    • 四、饿汉式单例模式
    • 五、懒汉式单例模式
  • 总结

前言

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,也是一种很常见的设计模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象


一、单例模式特点

下面我们来一张比较有意思的图说明:


这样单例模式保证一个类只有一个实例,减少了内存开销,尤其是那种频繁的创建和摧毁的场景,避免了对资源的多重占用,比如文件IO操作。

二、单例模式的优点

1、在内存里只有一个实例,减少了内存开销,尤其是那种频繁的创建和摧毁的场景。

2、避免对资源的多重占用,比如文件操作。

三、单例模式的缺点

1、没有接口,不能被继承,违背了单一职责设计原则,一个类应该只关心其内部业务逻辑,而不关心外部怎么实例化。

2、 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。

3、单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。 由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式。

四、饿汉式单例模式

首先创建单例模式类,私有化构造方法,一来就创建一个单例对象,表示很饥饿。

/*** @description: 单列模式* @author: dt* @date: 2021/4/5 12:16* @version: v1.0*/
public class Hungry {/*** 让构造函数为 private,这样该类就不会被实例化*/private Hungry() {}/*** 创造一个静态单例对象*/private final static Hungry HUNGRY = new Hungry();/*** 获取唯一可用的对象* @return*/public static Hungry getInstance(){return HUNGRY;}public void showMessage(){System.out.println("Hello World!");}
}

获取单例对象实例:

 public static void main(String[] args) {// 不可用被实例化,编译直接报错// Hungry hungry = new Hungry();// 获取唯一可用对象Hungry hungry = Hungry.getInstance();hungry.showMessage();}

但是这样的饿汉式模式是有问题的,会产生什么问题呢?

假设这里有四组资源,是非常耗内存的,浪费空间,我们应该在使用的时候再去加载,于是乎就有了懒汉式单列模式。

/*** @description: 单列模式* @author: dt* @date: 2021/4/5 12:16* @version: v1.0*/
public class Hungry {/*** 假设这里有四组资源,是非常耗内存的,浪费空间,我们应该在使用的时候再去加载*/private byte[] data1 = new byte[1024*1024];private byte[] data2 = new byte[1024*1024];private byte[] data3 = new byte[1024*1024];private byte[] data4 = new byte[1024*1024];/*** 让构造函数为 private,这样该类就不会被实例化*/private Hungry() {}/*** 创造一个单例对象*/private final static Hungry HUNGRY = new Hungry();/*** 获取唯一可用的对象* @return*/public static Hungry getInstance(){return HUNGRY;}public void showMessage(){System.out.println("Hello World!");}
}

五、懒汉式单例模式

/*** @description: 懒汉式单列模式* @author: ydf* @date: 2021/4/12 21:47* @version: v1.0*/
public class LazyMan {private LazyMan(){System.out.println(Thread.currentThread().getName());}public static LazyMan lazyMan;public static LazyMan getInstance(){// 不为null,我们才使用实例对象if(lazyMan==null){lazyMan = new LazyMan();}return lazyMan;}// 单线程下单列模式可以运行的,完全没问题,如果并发条件下就有问题了// 测试并发条件public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazyMan.getInstance();}).start();}}
}

打印结果:

单线程下单列模式可以运行的,完全没问题,如果并发条件下就有问题了。那么怎么解决呢?

加锁控制:双重检测锁模式

/*** @description: 懒汉式单列模式* @author: ydf* @date: 2021/4/12 21:47* @version: v1.0*/
public class LazyMan {private LazyMan(){System.out.println(Thread.currentThread().getName());}private volatile static LazyMan lazyMan;public static LazyMan getInstance(){// 加锁,双重检测一下if(lazyMan == null){synchronized (LazyMan.class){if(lazyMan == null){lazyMan = new LazyMan();}}}return lazyMan;}// 单线程下单列市客运的,如果并发条件下就有问题了// 测试并发条件public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{LazyMan.getInstance();}).start();}}
}


通过观察我们可以看到通过双重检测锁,保证了线程对象的唯一,测试成功。

总结

1、执行效率上:饿汉式没有加任何的锁,因此执行效率比较高。懒汉式一般使用都会加同步锁,效率比饿汉式差。

2、性能上:饿汉式在类加载的时候就初始化,不管你是否使用,它都实例化了,所以会占据空间,浪费内存。懒汉式什么时候需要什么时候实例化,相对来说不浪费内存。

3、饿汉式: 在类加载时就初始化创建单例对象,线程安全,但不管是否使用都创建对象可能会浪费内存。
4、懒汉式: 在外部调用时才会加载,线程不安全,可以加锁保证线程安全但效率低。

Java23种设计模式之单例模式相关推荐

  1. Java23种设计模式之单例模式的五种实现方式、反射破解单例模式、不能破解枚举单例模式详解

    源码链接(Gitee码云):https://gitee.com/oldou/javadesignpatterns 这里有我整理好的Java23种设计模式的源码以及博客教程,博客教程中介绍了Java23 ...

  2. java23种模式之单例模式

    JAVA23种设计模式四--单例模式 单例模式是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实 ...

  3. JAVA23种设计模式学习,源码+案例分析+类图讲解

    本文对JAVA中23种设计模式进行了简单的讲解,幷加以实际案例进行辅助理解,每种模式都会举例说明,幷将源码开源至gitee和githbu上.JAVA目录下为源码,resources目录下的UML文件夹 ...

  4. 走穿java23种设计模式-15责任链模式详解

    走穿java23种设计模式-15责任链模式详解 责任链模式是一种常见的行为模式. 一.责任链模式的现实场景 习伟过生日邀请了很多朋友到KTV一起庆祝,为了增加欢乐的气氛,习伟建议大家一起玩击鼓传花的游 ...

  5. 走穿java23种设计模式--18中介者模式详解

    走穿java23种设计模式–18中介者模式详解 中介者模式也称调停者模式,是一种比较简单的模式. 一.中介者模式的现实场景 蔡良因为上次表白时对方只看重他的物质方面,所以他对女朋友这个问题有点失望.因 ...

  6. java 23种设计模式 04 单例模式

    java 23种设计模式 04 单例模式 一.什么是单例模式 单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象.也就是说,在整个程序空间中,该类只存在一个实例对象.   ...

  7. JAVA23种设计模式(2)-结构型模式7种

    JAVA23种设计模式(2)-结构型模式7种 把类结合在一起形成更大的结构 适配器模式(adapter) 一句话:将一个类的接口转换成另一种接口.让原本接口不兼容的类可以兼容 这是平时比较常见的一种模 ...

  8. 24种设计模式之单例模式

    24种设计模式之单例模式  一.核心作用: 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. 二.常见的应用场景: 1.Windows的Task Manager(任务管理器)就是很典型的单 ...

  9. java-23种设计模式详解(一)

    2019独角兽企业重金招聘Python工程师标准>>>  设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反 ...

最新文章

  1. Teradata推出Vantage on Azure,可实现自助配置、快速部署,提供安全、可扩展的高性能分析
  2. linux 提交git,linux下git使用记录1 git 提交
  3. C++中set和map的erase用法
  4. 深度学习(七十四)半监督Mean teachers
  5. linux平台设备驱动模型是什么意思,Linux设备驱动模型之我理解
  6. 常用的Linux命令组合
  7. Memcache 缓存系统
  8. 阿里云CentOS7服务器搭建邮件服务器,端口:465
  9. ERP 集成常见的类型
  10. mcc_generated_files/eusart1.c:208:: error: (1098) conflicting declarations for variable “
  11. VR系列--VR介绍
  12. 计算机通过网口连接网络,使电脑连接网络的方法
  13. 免备案二级域名 长久稳定+已备案
  14. 6位你必须知道的产品大神
  15. OpenCV学习笔记
  16. 如何使用计算机语言画经纬网,使用R语言绘制中国地图
  17. 《Python程序设计与算法基础教程(第二版)》江红 余青松 课后选择题 课后填空题答案
  18. Spring(二) -- 春风拂面之 核心 AOP
  19. 用友云新愿望:一起生态一起赚钱 服务销售过亿元
  20. 微信拼手气红包算法(二倍平均值法)实现示范代码

热门文章

  1. 计算几何 —— 二维几何基础
  2. 凌乱的yyy(洛谷-P1803)
  3. 花生采摘(洛谷-P1086)
  4. 信息学奥赛C++语言:摘李子
  5. 信息学奥赛一本通C++语言——1060:均值
  6. 信息学奥赛一本通C++语言——1014:与圆相关的计算
  7. 23 SD配置-主数据-定义销售地区
  8. 55 MM配置-评估和科目设置-定义账户分类参考
  9. 19 CO配置-控制-产品成本控制-产品成本计划编制-定义日期控制
  10. 如何查阅资料?(找数据集,文献...)