单例模式示例_单例设计模式示例

单例模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.单例模式 2.如何使用单例模式创建类 3.何时使用Singleton 4.下载源代码

1.单例模式

有时对于某些类来说,只有一个实例很重要。 有许多对象,我们只需要它们的一个实例,而如果实例化多个对象,我们将遇到各种各样的问题,例如程序行为不正确,资源过度使用或结果不一致。

您可能只需要一个类的对象,例如,当您创建应用程序的上下文时,或者线程可管理的池,注册表设置,连接到输入或输出控制台的驱动程序等。该类型显然会导致程序不一致。

Singleton模式可确保一个类只有一个实例,并提供对其的全局访问点。 但是,尽管就类图而言,单例是最简单的,因为只有一个类,但是其实现却有些棘手。

图1

图1

在本课程中,我们将尝试不同的方法来仅创建该类的单个对象,还将看到一种方法比另一种方法更好。

2.如何使用单例模式创建类

创建这种类型的类的方法有很多种,但仍然可以看到一种方法比另一种更好。

让我们从一个简单的方法开始。

如果提供一个使对象可访问的全局变量该怎么办? 例如:

package com.javacodegeeks.patterns.singletonpattern;public class SingletonEager {public static SingletonEager sc = new SingletonEager();}

众所周知,一个类的静态变量只有一个副本,我们可以应用它。 就目前而言,客户端代码使用此sc静态变量就可以了。 但是,如果客户端使用新的运算符,则将有此类的新实例。

要停止在类之外实例化该类,让我们将该类的构造函数设为私有。

package com.javacodegeeks.patterns.singletonpattern;public class SingletonEager {public static SingletonEager sc = new SingletonEager();private SingletonEager(){}}

这行得通吗? 我想是的。 通过使构造函数保持私有状态,其他任何类都不能实例化该类。 获取此类对象的唯一方法是使用sc静态变量,该变量确保仅存在一个对象。

但是,众所周知,直接访问类成员并不是一个好主意。 我们将提供一种方法,通过该方法,sc变量将获得访问权,而不是直接访问。

package com.javacodegeeks.patterns.singletonpattern;public class SingletonEager {private static SingletonEager sc = new SingletonEager();private SingletonEager(){}public static SingletonEager getInstance(){return sc;}
}

因此,这是我们的单例类,可确保仅创建该类的一个对象,即使存在多个请求,也将仅返回相同的实例化对象。

这种方法的一个问题是,一旦将类加载到JVM中,就会立即创建对象。 如果从未请求过该对象,则内存中将有一个无用的对象。

在需要时创建对象始终是一种好方法。 因此,我们将在第一个调用中创建一个对象,然后在其他后续调用中返回相同的对象。

package com.javacodegeeks.patterns.singletonpattern;public class SingletonLazy {private static SingletonLazy sc = null;private SingletonLazy(){}public static SingletonLazy getInstance(){if(sc==null){sc = new SingletonLazy();}return sc;}
}

getInstance()方法中,我们检查静态变量sc是否为null,然后实例化该对象并将其返回。 因此,在第一次调用时,如果sc为null,则将创建对象,而在接下来的后续调用中,它将返回相同的对象。

这看起来确实不错,不是吗? 但是,此代码将在多线程环境中失败。 想象两个线程同时访问该类,线程t1首次调用getInstance()方法,它检查静态变量sc是否为null,然后由于某种原因而被中断。 另一个线程t2调用getInstance()方法成功通过了if检查并实例化了该对象。 然后,线程t1醒来,它还创建了对象。 此时,将有两个此类。

为了避免这种情况,我们将使用synchronized关键字到getInstance()方法。 通过这种方式,我们强制每个线程等待其轮换才能进入该方法。 因此,没有两个线程会同时进入该方法。 同步带有价格,它会降低性能,但是如果对getInstance()方法的调用不会给您的应用程序造成实质性开销,则请忽略它。 另一个解决方法是转向渴望的实例化方法,如前面的示例所示。

package com.javacodegeeks.patterns.singletonpattern;public class SingletonLazyMultithreaded {private static SingletonLazyMultithreaded sc = null;private SingletonLazyMultithreaded(){}public static synchronized SingletonLazyMultithreaded getInstance(){if(sc==null){sc = new SingletonLazyMultithreaded();}return sc;}
}

但是,如果要使用同步,还有另一种称为“双重检查锁定”的技术可以减少同步的使用。 使用双重检查锁定,我们首先检查是否创建了实例,如果没有创建,则进行同步。 这样,我们只同步第一次。

package com.javacodegeeks.patterns.singletonpattern;public class SingletonLazyDoubleCheck {private volatile static SingletonLazyDoubleCheck sc = null;private SingletonLazyDoubleCheck(){}public static SingletonLazyDoubleCheck getInstance(){if(sc==null){synchronized(SingletonLazyDoubleCheck.class){if(sc==null){sc = new SingletonLazyDoubleCheck();}	}}return sc;}
}

除此之外,还有其他打破单例模式的方法。

  1. 如果该类是Serializable。
  2. 如果是可克隆的。
  3. 可以通过反思来打破。
  4. 同样,如果该类由多个类加载器加载。

下面的示例说明如何保护您的类免于被多次实例化。

package com.javacodegeeks.patterns.singletonpattern;import java.io.ObjectStreamException;
import java.io.Serializable;public class Singleton implements Serializable{private static final long serialVersionUID = -1093810940935189395L;private static Singleton sc = new Singleton();private Singleton(){if(sc!=null){throw new IllegalStateException("Already created.");}}public static Singleton getInstance(){return sc;}private Object readResolve() throws ObjectStreamException{return sc;}private Object writeReplace() throws ObjectStreamException{return sc;}public Object clone() throws CloneNotSupportedException{throw new CloneNotSupportedException("Singleton, cannot be clonned");}private static Class getClass(String classname) throws ClassNotFoundException {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();if(classLoader == null) classLoader = Singleton.class.getClassLoader();return (classLoader.loadClass(classname));}}
  1. 在您的单例类中实现readResolve()writeReplace()方法,并通过它们返回相同的对象。
  2. 您还应该实现clone()方法并引发异常,以使单例无法被克隆。
  3. 构造函数中的“ if条件”可以防止使用反射多次实例化单例。
  4. 为了防止从不同的类加载器实例化单例,可以实现getClass()方法。 上面的getClass()方法将类加载器与当前线程关联; 如果该类加载器为null,则该方法使用与加载单例类相同的类加载器。

尽管我们可以使用所有这些技术,但是有一种简单的方法可以创建单例类。 从JDK 1.5开始,您可以使用枚举创建单例类。 枚举常量是隐式静态的和最终的,创建后就无法更改其值。

package com.javacodegeeks.patterns.singletonpattern;public class SingletoneEnum {public enum SingleEnum{SINGLETON_ENUM;}
}

当您尝试显式实例化Enum对象时,将出现编译时错误。 当Enum静态加载时,它是线程安全的。 Enum中的clone方法是最终的,可确保枚举常量永远不会被克隆。 枚举本质上是可序列化的,序列化机制可确保不会因反序列化而创建重复的实例。 也禁止使用反射实例化。 这些确保了枚举实例不存在超出枚举常量定义的实例。

3.何时使用Singleton

  1. 一个类必须完全有一个实例,并且客户端必须可以从一个著名的访问点访问它。
  2. 当唯一的实例可以通过子类扩展,并且客户端应该能够使用扩展的实例而无需修改其代码。

4.下载源代码

这是有关Singleton Pattern的课程。 您可以在此处下载源代码: SingletonPattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/singleton-design-pattern.html

单例模式示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336966.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解读C++即将迎来的重大更新(一):C++20的四大新特性

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络C20(C 编程语言标准 2020 版)将是 C 语言一次非常重大的更新,将为这门语言引入大量新特性。…

小尼机器人_小尼被机器人嫌弃“唱歌难听,长相一般”?

我们如今所处的时代,科技创新的速度日新月异,生活方式多彩多姿。人人都说:科技改变了生活。今晚《开门大吉》也迎来了三大改变生活的神奇黑科技!智能且生态的“移动城堡”在网上预定好酒店以后,到了现场没有前台和服务员&#xff…

产品原型示例_原型设计模式示例

产品原型示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

13 年,MySQL 之父赌赢了:另起炉灶的 MariaDB 成功上市!

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络,侵权删!今年 2 月,开源数据库厂商 MariaDB 完成了 1.04 亿美元的 D 轮融资,同…

太阳粒子是什么东西_太阳光子前世今生告诉我们现在享受之阳光是十几万年前诞生的老光...

我们都知道天晴时阳光明媚,但这个阳光是怎么来的呢,很多人就不一定清楚了。在这里我们首先来了解几个概念:光子、光、电磁波、电磁辐射。光子是传递电磁波相互作用的基本粒子,是一种规范波色子,是电磁辐射的载体&#…

java 观察者模式示例_观察者设计模式示例

java 观察者模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 …

int类型存小数 mysql_MySQL基本数据类型

1)整形1.介绍分类:tinyint , smallint , mediumint , int , bigint 应用场景:存储年龄,等级,id,各种号码等典型存储范围介绍:https://images2017.cnblogs.com/blog/1036857/201708/1036857-201708011814337…

枚举重名_举重设计模式示例

枚举重名本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01…

装饰着模式示例_装饰器设计模式示例

装饰着模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &…

强烈推荐!10个超赞的C语言开源项目

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络今天给大家分享10个超赞的C语言开源项目,希望这些内容能对大家有所帮助!01WebbenchWebbench是一个在 L…

以外的文件 删除_原来C盘还可以删除这五个文件,难怪电脑越来越卡!

马上就要年底了,大家肯定都是欢欢喜喜准备过年,将家里变得焕然一新。韩博士也捯饬好大包小包打算风风火火赶回家,结果刚打开电脑,哦豁,立马卡到爆炸。想着都年底了,这电脑还打算给我搞出什么幺蛾子&#xf…

设计模式示例_复合设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

给大家收集了一些C语言代码优化的方法!

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络在本篇文章中,我收集了很多经验和方法。应用这些经验和方法,可以帮助我们从执行速度和内存使用等方面来…

设计模式示例_介体设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

清空list_还在为邮箱爆掉而烦恼吗?学会清空你的收件箱

less is more | 越不繁,越不凡还在为邮箱爆掉而烦恼吗?学会清空你的收件箱我一般只用Gmail收发邮件,而且处理邮件已经成为日常工作的核心之一。我每个小时能收到大量邮件,并且快速回复。但是,有一件事要特别提一下&…

这才是B站的正确打开方式!

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络每天都在用B站刷杂七杂八的视频,有没有考虑过挖掘一些优质UP主?想要发掘优质UP主,靠B站官方…

pcl_openmap_OpenMap教程–第1部分

pcl_openmap介绍 本系列教程将向您展示如何使用OpenMap GIS Java Swing库构建Java应用程序。 OpenMap的开发人员指南是非常有用的文档,描述了OpenMap的体系结构,但没有说明如何逐步启动和构建应用程序。 源代码附带的示例很有用,但还不够。 …

网页编程从入门到精通 杨凡_干货 | web前端入门基础知识

一名合格的web前端工程师必须得掌握HTML、CSS和JavaScript。只懂其中一个或两个还不行,你必须对这三门语言都很熟悉。也不是说必须对这三门语言都非常精通,但你至少要能够运用它们完成大多数任务,而无需地频繁地寻求别人的帮助。今天给大家分…

100 个网络基础知识

关注星标,每天学习C语言新技能因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源:网络1)什么是链接?链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。2)OSI 参考模型的层次…

策略模式示例代码_策略设计模式示例

策略模式示例代码本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &am…