抽丝剥茧 细说架构那些事——【优锐课】

单例模式可确保在给定的时间实例中只能创建一个具有全局访问点的对象。这是面向对象编程中最常用的技术之一。尽管它很简单,但从类设计的角度来看可能是最简单的,但是在尝试实现它们之前,必须先解决一些细微的问题。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。通过引用Java代码示例来深入探索这种模式。

总览

在某些情况下,系统应在给定的时间点仅允许一个类的对象存储在内存中。这意味着,当程序实例化该对象时,不应允许该程序创建该类的其他对象。例如,在连接到数据库的系统中,仅使用一个对象来管理数据库连接。这样可以确保其他对象无法初始化不必要的连接,从而由于多个实例化而使系统的整体性能下降。通过创建多个JDBC连接并观察性能,可以很容易地对其进行测试。性能肯定会受到影响或显着降低。单例模式实质上可以保证系统仅创建一个类的实例。

单例模式

使用单例模式是确保给定类实例化一个且只有一个对象的一种标准技术。这是“四人帮”讨论的二十四个设计模式之一。想法是解决诸如实例化类的单个实例,访问类的唯一实例或控制类实例化过程的问题。实现此目的的关键技术是通过使用私有修饰符隐藏构造函数,并提供一种应用检查和验证的方法,以确保仅创建该类的一个实例。

这很简单,但有效地满足了需求。实际上,通过应用相同的原理,我们可以控制创建类的实例的确切数目,而不仅限于单个实例。但是,这里我们仅关注单个实例。

使用单例模式

不难发现实际上我们只需要一个类的一个实例在内存中的情况。多个对象可能会破坏原因或对正在运行的应用程序的性能造成破坏。在面向对象的编程中,正在运行的应用程序通常在内存中具有许多对象,它们在执行过程中相互作用并扮演着至关重要的角色。但是,在实现线程池,高速缓存,对话框或负责首选项和注册表设置的对象时,数据库连接,日志记录,充当外围设备或图形卡设备驱动程序的对象等都是我们想要的情况。对象运行的单个实例;否则,它将产生很多问题,例如资源阻塞,内存过载以及许多其他不一致的行为。这正是我们需要确定适合于实现单例模式的类并进行相应设计的地方。

实现单例模式

这是该模式的快速实现。

 public final class Singleton {
private static final Singleton singleInstance =
new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return singleInstance;
}
} public class TestSingleton {
public static void main(String[] args){
Singleton s1;
Singleton s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
if(s1 == s2){
System.out.println("References to same
Singleton object");
}
}
}

Singleton类被声明为final,因此无法创建任何子类。这甚至限制了多重实例化,即使通过对该类进行子类化。构造函数被声明为私有;结果,只有Singleton类可以使用此构造函数创建Singleton对象。对Singleton对象的静态引用将调用私有构造函数,并仅提供该类的一个实例。调用getInstance() 方法时,仅接收对象的参考副本。

在这里,我们通过创建另一个称为TestSingleton的类来使用一个简单的测试。此类声明两个参考Singleton对象,并调用getInstance()方法。然后,我们比较这两个引用,以确保它们实际上引用的是同一运行时实例,而不是两个不同的对象。

有时,我们需要一个仅在第一个静态方法被调用时才创建实例的实现,而不是在此之前。在前面的示例中,对象是静态创建的;getInstance()方法的作用是简单地返回引用。在这种情况下,我们希望在首次调用时创建对象,称为延迟初始化。另外,我们希望调用是线程安全的;否则,可能导致奇怪的不稳定行为或内存泄漏,从而导致JVM崩溃。这是实现此目的的示例。

 public final class Singleton {
private static volatile Singleton singleInstance =
null;
private Singleton(){
}
public static Singleton getInstance(){
if (singleInstance == null) {
synchronized(Singleton.class) {
if (singleInstance == null) {
singleInstance = new Singleton();
}
}
}
return singleInstance;
}
} public class TestSingleton {
public static void main(String[] args){
Singleton s1;
Singleton s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
if(s1 == s2){
System.out.println("References to same
Singleton object");
}
}
}

也可以使用Enum实现单例。实际上,在可能的情况下,最好使用Enum代替类来实现单例模式。JVM保证从单例Enum中只能创建一个实例。

 public enum SingletonEnum {
SINGLEINSTANCE;
public void someMethod(){
// ...
}
} public class TestSingleton {
public static void main(String[] args){
SingletonEnum s1;
SingletonEnum s2;
s1 = SingletonEnum.SINGLEINSTANCE;
s2 = SingletonEnum.SINGLEINSTANCE;
if (s1 == s2){
System.out.println("References to same
Singleton object");
}
}
}

结论

与往常一样,用户的自由裁量权是良好设计的关键,因为不当使用单例模式可能会导致其他问题。如果单例执行复杂且重量级的操作,则很难对其进行测试。更好的建议是使用依赖项注入框架来构造单个对象。在诸如在GUI应用程序中创建对话框或很少有并发用户的情况下,单例效果最佳。单例模式虽然有用,但在大型可扩展应用程序中造成性能瓶颈方面臭名昭著。

感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。下篇继续~

深入探索Java设计模式(二)之策略模式

深入探索Java设计模式(三)之装饰器模式

深入探索Java设计模式(四)之享元模式

深入探索Java设计模式(五)之构建器模式

深入探索Java设计模式之单例模式的更多相关文章

  1. 深入探索Java设计模式(二)之策略模式

    策略设计模式是Java API库中常见的模式之一.这与另一个设计模式(称为状态设计模式)非常相似.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题]中<学习源码中的优秀设计模式> ...

  2. 深入探索Java设计模式(三)之装饰器模式

    装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...

  3. 深入探索Java设计模式(四)之享元模式

    享元模式适用于需要大量相同类型对象的情况.在此,设计布局可以减少创建多个对象的方式.对象在运行时会消耗资源,因此最好在内存中使用较少的对象.它减少了内存占用并利用了程序的整体性能.本文是在学习完优锐课 ...

  4. 深入探索Java设计模式之构建器模式(五)

    抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...

  5. java 设计模式之单例模式

    -------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...

  6. 折腾Java设计模式之单例模式

    博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...

  7. Java设计模式之单例模式(七种写法)

    Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...

  8. Java 设计模式之单例模式(一)

    原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...

  9. java设计模式1——单例模式

    java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...

随机推荐

  1. 领扣(LeetCode)第三大的数 个人题解

    给定一个非空数组,返回此数组中第三大的数.如果不存在,则返回数组中最大的数.要求算法时间复杂度必须是O(n). 示例 1: 输入: [3, 2, 1] 输出: 1 解释: 第三大的数是 1. 示例 2 ...

  2. 防火墙和SELinux

    在/etc/sysconfig/selinux中修改SELINUX=disabled关闭SELinux 执行systemctl disable firewalld关闭防火墙 然后重启计算机

  3. word使用指南(经常更新)

    一.快捷键 Ctrl+C 复制 Ctrl+X 剪切 Ctrl+V 粘贴 Ctrl+F 查找 Ctrl+A 全选 Ctrl+Z/Y 撤销/还原撤销 Ctrl+D 打开字体对话框 Ctrl+S 另存为 C ...

  4. python的time、datetime和calendar

    datetime模块主要是用来表示日期的,就是我们常说的年月日时分秒,calendar模块主要是用来表示年月日,是星期几之类的信息,time模块主要侧重点在时分秒,从功能简单来看,我们可以认为三者是一 ...

  5. 2019 牛客网 第七场 H pair

     题目链接:https://ac.nowcoder.com/acm/contest/887/H  题意: 给定A,B,C问在[1,A]和[1,B]中有多少对x,y满足x&y>C或者x^y ...

  6. Intellij 生成exe可执行文件

    生成jar包 编写源代码 此处我使用kotlin来编码,主函数实际功能就是输出一行文字. /** * 应用入口 * @author mazaiting */ object TestExe { ​ @J ...

  7. 负载均衡集群介绍、LVS介绍、LVS调度算法、LVS NAT模式搭建

    7月4日任务 18.6 负载均衡集群介绍18.7 LVS介绍18.8 LVS调度算法18.9/18.10 LVS NAT模式搭建 扩展lvs 三种模式详解 http://www.it165.net/a ...

  8. java 算法之 两个字符串中最大相同的子串

    public class String_intern { public static void main(String[] args) { String old="aaaaabc1" ...

  9. 关于ios沙盒

    沙盒下主要有四个文件夹:document,caches,tmp,library document 的路径  程序运行时生成的文件,这个文件不要存比较放大的文件,比如音频,视频类,因为这里的东西会被上传 ...

  10. JQuery动态添加控件并取值

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...