深入探索Java设计模式之单例模式
抽丝剥茧 细说架构那些事——【优锐课】
单例模式可确保在给定的时间实例中只能创建一个具有全局访问点的对象。这是面向对象编程中最常用的技术之一。尽管它很简单,但从类设计的角度来看可能是最简单的,但是在尝试实现它们之前,必须先解决一些细微的问题。本文是在学习完优锐课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 API库中常见的模式之一.这与另一个设计模式(称为状态设计模式)非常相似.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题]中<学习源码中的优秀设计模式> ...
- 深入探索Java设计模式(三)之装饰器模式
装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...
- 深入探索Java设计模式(四)之享元模式
享元模式适用于需要大量相同类型对象的情况.在此,设计布局可以减少创建多个对象的方式.对象在运行时会消耗资源,因此最好在内存中使用较少的对象.它减少了内存占用并利用了程序的整体性能.本文是在学习完优锐课 ...
- 深入探索Java设计模式之构建器模式(五)
抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...
- java 设计模式之单例模式
-------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...
- 折腾Java设计模式之单例模式
博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...
- Java设计模式之单例模式(七种写法)
Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...
- Java 设计模式之单例模式(一)
原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...
- java设计模式1——单例模式
java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...
随机推荐
- nyoj 214-单调递增子序列(二) (演算法,PS:普通的动态规划要超时)
214-单调递增子序列(二) 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:11 submit:35 题目描述: 给定一整型数列{a1,a2..., ...
- JavaWeb核心知识点
一:HTTP协议 一.概述 1. 概念:超文本传输协议 2. 作用:规范了客户端(浏览器)和服务器的数据交互格式 3. 特点 1. 简单快速:客户端向服务器请求服务时,仅通过键值对来传输请求方 ...
- django:runserver实现远程访问
如果是在另一台电脑上web访问要用 python manage.py ip:port (一般使用8000)的形式:监听所有ip用0.0.0.0如下: 1 2 3 python manage.py ru ...
- Java虚拟机详解(九)------类文件结构
我们知道计算机是由晶体管.电路板等组装而成的电子设备,而这些电子设备其实只能识别0与1的信号. 那么问题来了,我们在操作系统上编写的Java代码(由字母.数字等各种符号组成),打包后部署到服务器上,是 ...
- windows 10 上源码编译boost 1.66.0 | compile boost 1.66.0 from source on windows 10
本文首发于个人博客https://kezunlin.me/post/854071ac/,欢迎阅读! compile boost 1.66.0 from source on windows 10 Ser ...
- Linux\Nginx 虚拟域名配置及测试验证
使用 Nginx 虚拟域名配置,可以不用去购买域名,就可以通过特定的域名访问本地服务器.减少发布前不必要的开支. 配置步骤 1. 编辑 nginx.conf 配置文件 sudo vim /usr/lo ...
- 两步搞定Activity的向右滑动返回的功能
向右滑动返回,对于屏幕过大的手机来说,在单手操作时,是一个不错的用户体验,用户不必再费力的或者用另一个手去点击屏幕左上角的返回按钮或者,手机右下角的返回按钮,轻轻向右滑动屏幕即可返回上一页,这个功能如 ...
- [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList
一.线性表 1,什么是线性表 线性表就是零个或多个数据元素的有限序列.线性表中的每个元素只能有零个或一个前驱元素,零个或一个后继元素.在较复杂的线性表中,一个数据元素可以由若干个数据项组成.比如牵手排 ...
- python数据分析pandas中的DataFrame数据清洗
pandas中的DataFrame中的空数据处理方法: 方法一:直接删除 1.查看行或列是否有空格(以下的df为DataFrame类型,axis=0,代表列,axis=1代表行,以下的返回值都是行或列 ...
- Debug 利器:pstack & strace
工作中难免会遇到各种各样的 bug,对于开发环境 or 测试环境的问题还好解决,可以使用 gdb 打断点或者在代码中埋点来定位异常; 但是遇到线上的 bug 就很难受了,由于生产环境不能随意替换.中断 ...