一般情况下单例模式的代码实现如下 👇
package singleton;
/**
-
@author mengzhichao
-
@create 2021-11-28-15:47
*/
public class Singleton {
private static Singleton instance=null; //静态私有成员变量
//私有构造函数
private Singleton(){
}
//静态共有工厂方法,返回唯一实例
public static Singleton getInstance(){
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
为了测试单例类所创建对象的唯一性,可以编写如下客户端测试代码
package singleton;
/**
-
@author mengzhichao
-
@create 2021-11-28-15:51
*/
public class Client {
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
System.out.println(s1==s2);
}
}
编译代码并运行,输出结果为:true
- 说明两次调用getInstance()时所获取的对象是同一实例对象,且无法在外部不Singleton进行实例化,因而确保系统中只有唯一的一个Singleton对象。
在单例模式的实现过程中,需要注意以下几点:
-
单例类的构造函数为私有。
-
提供一个自身的静态私有成员变量。
-
提供一个公有的静态工厂方法。
-
getInstance()方法中需要使用同步锁synchronized (Singleton.class)防止多线程同时进入造成 instance 被多次实例化。
=======================================================================
场景一
- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
场景二
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
使用单例模式有一个必要条件: 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式。
不适用场景
-
不要使用单例模式存取全局变量,因为这违背了单例模式的用意,最好将全局变量放到对应类的静态成员中。
-
不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。单例模式由于使用静态成员存储类的实例,所以可能会造成资源无法及时释放,带来一些问题。
========================================================================
主要优点在于提供了对唯一实例的受控访问并可以节约系统资源。
-
在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
-
避免对资源的多重占用(比如写文件操作)
其主要缺点在于因为缺少抽象层而难以扩展,且单例类职责过重。
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
=======================================================================
- 如java. lang.Runtime类。
在每一个Java应用程序里面,都有唯一的一个Runtime对象,通过这个Runtime对象,应用程序可以与其运行环境发生相互作用。在JDK中,Runtime类的源代码片段如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
…
}
当我们试图要从 Spring容器中获取某个类的实例时,默认情况下Spring会通过单例模式进行创建,也就是在Spring 的 bean 工厂中这个bean的实例只有一个,代码如下:
- 在现实生活中,居民身份证号码具有唯一性,同一个人不允许有多个身份证号码,第一次申请身份证时将给居民分配一个身份证号码,如果之后因为遗失等原因补办时,还是使用原来的身份证号码,不会产生新的号码。
现使用单例模式模拟该场景。
- 创建单例类 IdentityCardNo(身份证号码类)
在单例类IdentityCardNo中除了静态工厂方法外,还可以包含一些其他业务方法﹐如本例中的setIdentityCardNo()方法和 getIdentityCardNo()方法。在工厂方法 getInstance()中,先判断对象是否存在,如果不存在则实例化一个新的对象﹐然后返回;如果存在则直接返回已经存在的对象。
package singletontest;
/**
-
@author mengzhichao
-
@create 2021-11-28-16:18
*/
public class IdentityCardNo {
private static IdentityCardNo instance = null;
private String no;
private IdentityCardNo() {
}
public static IdentityCardNo getInstance(){
if (instance==null){
System.out.println(“第一次办理身份证,分配新号码”);
instance=new IdentityCardNo();
instance.setIdentityCardNo(“No410111111122222222”);
结语
小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。
我们选择的这个行业就一直要持续的学习,又很吃青春饭。
虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。
送给每一位想学习Java小伙伴,用来提升自己。
本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!
11122222222");
结语
小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。
我们选择的这个行业就一直要持续的学习,又很吃青春饭。
虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。
送给每一位想学习Java小伙伴,用来提升自己。
[外链图片转存中…(img-jWoegOxa-1714800337886)]
本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!