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

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

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5 ...

  2. Pashmak and Parmida's problem(树状数组)

    题目链接:http://codeforces.com/contest/459/problem/D 题意: 数列A, ai表示 i-th 的值, f(i,j, x) 表示[i,j]之间x的数目, 问:当 ...

  3. 扛把子组20191017-5 alpha week 2/2 Scrum立会报告+燃尽图 04

    此作业要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/9801] 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 ...

  4. Java w3c离线手册

    提供给大家使用,懒得找: 前端后端一般都用的到  查看文档 1. JDK_API_1_6_zh_CN.CHM 2.     W3School离线手册(2018.04.01).chm 3.    jqu ...

  5. iOS 抽奖轮盘效果实现思路

    临近活动,相信不少app都会加一个新的需求——抽奖不多废话,先上GIF效果图 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这是一个我的iOS交流群:937194184,不管你是小白还是大牛欢 ...

  6. Hystrix完整配置列表

    前提 Hystrix在2018年11月20日之后已经停止维护,最后一个提交记录是:Latest commit 3cb2158 on 20 Nov 2018,最后一个正式版本为1.5.18.鉴于目前所在 ...

  7. mysql的事物,外键,与常用引擎

    ### part1 时间类型 date YYYY-MM-DD 年月日 (出现日期) time HH:MM:SS 时分秒 (竞赛时间) year YYYY 年份值 (红酒年份 82年矿泉水) datet ...

  8. 在Kubernetes上运行有状态应用:从StatefulSet到Operator

    一开始Kubernetes只是被设计用来运行无状态应用,直到在1.5版本中才添加了StatefulSet控制器用于支持有状态应用,但它直到1.9版本才正式可用.本文将介绍有状态和无状态应用,一个通过K ...

  9. 单像空间后方交会(python实现)

    原理:空间后方交会是以单幅影像为基础,从该影像所覆盖地面范围内若干控制点的已知地面坐标和相应点的像坐标量测值出发,根据共线条件方程,解求该影像在航空摄影时刻的外方位元素Xs,Ys,Zs,φ,ω,κ. ...

  10. 安装iris框架

    1.导语 目前Go语言已经为大多数人所熟知,越来越多的开发人员选择使用Go语言来进行开发,但是如何使用 Go来进行web开发,在其他编程语言中都有对应的开发框架,当然在Go中也有,就是即将要介绍的-- ...