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

单例模式可确保在给定的时间实例中只能创建一个具有全局访问点的对象。这是面向对象编程中最常用的技术之一。尽管它很简单,但从类设计的角度来看可能是最简单的,但是在尝试实现它们之前,必须先解决一些细微的问题。本文是在学习完优锐课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. nyoj 21-三个水杯(BFS)

    21-三个水杯 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:7 submit:18 题目描述: 给出三个水杯,大小不一,并且只有最大的水杯的水是装 ...

  2. nyoj 46-最少乘法次数 (递推)

    46-最少乘法次数 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:5 submit:18 题目描述: 给你一个非零整数,让你求这个数的n次方,每次相 ...

  3. C语言作业|08

    问题 答案 这个作业的属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/9977 我 ...

  4. usaco training <1.2 Your Ride Is Here>

    题面 Your Ride Is Here It is a well-known fact that behind every good comet is a UFO. These UFOs often ...

  5. python requirements.txt的创建及使用

    要求文件(requirements.txt)是安装包的依赖项及版本的记录文件. pip: 创建 (venv) $ pip freeze >requirements.txt 使用 (venv) $ ...

  6. Mac安装和卸载Mysql

    目录 一.安装 二.环境变量 2.1 MySQL服务的启停和状态的查看 三.启动 四.初始化设置 4.1 退出sql界面 五.配置 5.1 检测修改结果 一.安装 第一步:打开网址,https://w ...

  7. Feature Fusion for Online Mutual Knowledge Distillation (CVPR 2019)

    一.解决问题 如何将特征融合与知识蒸馏结合起来,提高模型性能 二.创新点 支持多子网络分支的在线互学习 子网络可以是相同结构也可以是不同结构 应用特征拼接.depthwise+pointwise,将特 ...

  8. centos7关闭默认firewall,启用iptables

    CentOS 7.0默认使用"firewall"防火墙 一:关闭firewall1.直接关闭防火墙systemctl stop firewalld.service 2.禁止fire ...

  9. createTextNode

    createTextNode()方法将创建一个包含给定文本的新文本文档节点.这个方法的返回值是一个指向新建文本节点的引用指针: reference = document.createTextNode( ...

  10. HTML标签的for属性

    HTML 标签的 for 属性 for 属性规定 label 与哪个表单元素绑定. 隐式和显式的联系 label通常以下面两种方式中的一种来和表单控件相联系: 将表单控件作为标记标签的内容,这样的就是 ...