单例设计模式是一种软件设计模式,用于将类的实例化限制为一个对象。
与其他创建设计模式(例如抽象工厂 , 工厂和构建器模式)相比,单例将创建一个对象,但也将负责,因此该对象只有一个实例存在。

当创建一个单例类时,必须解决一些特定问题。

  • 如何确保一个类只有一个实例。
  • 如何轻松访问类的唯一实例
  • 类如何控制其实例化
  • 如何限制一个类的实例数

假设我们有一个发送消息的类。
Messenger类。

package com.gkatzioura.design.creational.singleton;public class Messenger {public void send(String message) {}
}

但是,我们希望消息过程仅由Messenger类的一个实例处理。 想象一下Messenger类打开一个tcp连接(例如xmpp)并且必须保持该连接活动以便发送消息的情况。 每次我们必须发送一条消息时,打开一个新的xmpp连接都是非常低效的。

因此,我们将继续使Messenger类成为单例。

package com.gkatzioura.design.creational.singleton;public class Messenger {private static Messenger messenger = new Messenger();private Messenger() {}public static Messenger getInstance() {return messenger;}public void send(String message) {}
}

如您所见,我们将Messenger构造函数设置为私有,并使用静态变量初始化了Messenger。
静态变量是类级别的变量,仅当将类加载到内存中时,内存分配才发生一次。 通过这种方式,我们确保将使Messenger类仅实例化一次。 一旦被调用,getInstance方法将获取静态Messenger实例。

显然,以前的方法有其优点和缺点。 我们不必担心线程安全,仅在加载Messenger类时才创建实例。 但是,它缺乏灵活性。 考虑将配置变量传递给Messenger构造函数的场景。 使用以前的方法是不可能的。

一种解决方法是在getInstance方法上实例化Messenger类。

package com.gkatzioura.design.creational.singleton.lait;public class Messenger {private static Messenger messenger;private Messenger() {}public static Messenger getInstance() {if(messenger==null) {messenger = new Messenger();}return messenger;}public void send(String message) {}
}

上面的方法在某些情况下可能有效,但是在类可能在多线程环境中实例化的情况下,它会丢失线程安全性。

使我们的类线程安全的最简单方法是同步getInstance方法。

package com.gkatzioura.design.creational.singleton.lait;public class Messenger {private static Messenger messenger;private Messenger() {}public synchronized static Messenger getInstance() {if(messenger==null) {messenger = new Messenger();}return messenger;}public void send(String message) {}
}

那将工作。 至少将使Messenger的创建同步,并且不会创建任何重复项。 这种方法的问题在于,在创建对象时仅需要同步一次。 使用上面的代码将导致不必要的开销。

另一种方法是使用双重检查锁定方法。 现在,经过双重检查的锁定需要格外小心,因为很容易从正确的选择中找出损坏的实现 。
最好的方法是使用volatile关键字实现延迟加载。

package com.gkatzioura.design.creational.singleton.dcl;public class Messenger {private static final Object lock = new Object();private static volatile Messenger messenger;private Messenger() {}public static Messenger getInstance() {if(messenger==null) {synchronized (lock) {if(messenger==null) {messenger = new Messenger();}}}return messenger;}public void send(String message) {}
}

通过使用volatile关键字,我们可以防止对volatile的写入相对于任何先前的读取或写入进行重新排序,并防止对volatile的读取相对于随后的任何读取或写入进行重新排序。 互斥对象也用于实现同步。

总而言之,我们创建了一个对象,并确保该对象只有一个实例。 我们还确保在多线程环境中实例化对象不会有任何问题。

您可以在github上找到源代码。

在下一篇博客文章中,我们将介绍原型模式。

另外,我还编写了备忘单,其中包含“创作设计模式”的摘要。 在链接中注册以接收它。

翻译自: https://www.javacodegeeks.com/2018/03/creational-design-patterns-singleton-pattern.html

创新设计模式:单例模式相关推荐

  1. Python设计模式-单例模式

    Python设计模式-单例模式 基于Python3.5.2,代码如下 #coding:utf-8 import threading import timeclass Singleton(object) ...

  2. Android设计模式——单例模式(Singleton)

    二十三种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元 ...

  3. 【学习笔记】ABAP OOD设计模式 - 单例模式

    ABAP OOD设计模式 - 单例模式 整理转自-<SAP ABAP 面向对象程序设计(原则.模式及实践)> 单例模式(Singleton Pattern)是常用的且较为简单的软件设计模式 ...

  4. Go 语言实现 23 种设计模式 单例模式

    Go 语言实现 23 种设计模式 单例模式 单例模式 单例模式是一种常用的软件设计模式,在使用过程中,单例对象的类只有一个实例.使用单例模式,1 可以节省内存等资源,例如windows操作系统的资源管 ...

  5. java singleton inner class_Java面向对象设计模式-单例模式

    Java面向对象设计模式-单例模式 2020-05-28 589 0 单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,有多重实现方式. 一.饿汉式单例模式,构造方法私有化,在加载类Sin ...

  6. Java开发中常用的设计模式-单例模式

    单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式. Java开发中常用的设计模式-单例模式 单例模式有3个特点: 单例类只有一个实例对象: 该单例对象必须 ...

  7. 炒冷饭系列:设计模式 单例模式

    2019独角兽企业重金招聘Python工程师标准>>> 炒冷饭系列:设计模式 单例模式 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆 ...

  8. 设计模式-单例模式-注册式单例模式-枚举式单例模式和容器式单例模式在Java中的使用示例

    场景 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例: 设计模式-单例模式-饿汉式单例模式.懒汉式单例模式.静态内部类在Java中的使用示例_霸道流氓气质的博客- ...

  9. 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)

    创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...

  10. 小视频源码,设计模式单例模式

    小视频源码,设计模式单例模式实现的相关代码 .一,单线程时候推荐 /*** Created by Shinelon on 2018/10/11.* 单利模式 懒汉式 -->单线程推荐使用*/pu ...

最新文章

  1. 【BUG】小米5中 video.js 在钉钉 webview 中全屏后 后退无法弹出虚拟键盘
  2. [RDLC]报表根据字段列动态加载图片(二)
  3. boost::process::std_err日历相关的测试程序
  4. SAP Spartacus cms service取完page信息后的回调callback
  5. android可扩展列表,android-可扩展列表视图未显示
  6. lightoj 1031 区间dp
  7. 模糊PID控制算法 之 C语言实现
  8. VDN互联网数据驱动 FOR PB
  9. 计算机管理员怎么转让,钉钉怎么转让主管理员身份? 钉钉更换主管理员的技巧...
  10. pdf怎么转换成图片?
  11. Datax-HdfsWriter如何实现支持decimal类型数据写入
  12. 多种方法教你如何让手机免费上网
  13. YOLOv5目标检测算法——通俗易懂的解析
  14. 记一次App异常kill分析处理
  15. c++ Primer Plus笔记
  16. MLY -- 11.When to change dev/test sets and metrics
  17. RAW图像数据到RGB
  18. 北京图灵学院 Python(02)
  19. [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构
  20. 各个厂商手机不打印log日志的解决方法

热门文章

  1. Spring Cloud面试题(2020最新版)
  2. 一次堆外OOM问题的排查过程
  3. Java Socket编程----通信是这样炼成的
  4. 教你如何监控 Java 线程池运行状态
  5. java之StringBuider与StringBuffer
  6. Python基础案例(一)
  7. 2017蓝桥杯省赛---java---A---2(9数算式)
  8. jquery官网打不开难以下载,不妨试试webjars
  9. IDEA开启Run Dashboard窗口
  10. antd vue表单上传文件_vue+axios+antD的上传图片踩坑