💁 个人主页:Nezuko627的博客主页
❤️ 支持我:👍 点赞 🌷 收藏 🤘关注
🎏 格言:立志做一个有思想的程序员 🌟
📫 作者介绍:本人本科软件工程在读,博客将主要分享JavaSE、JavaEE、MySQL、SpringBoot、算法等知识。专栏内容长期更新,如有错误,欢迎评论区或者私信指正!感谢大家的支持~~~
文章目录本篇学习目标:
- ⭐️ 了解什么是单例模式;
- ⭐️ 掌握饿汉式单例模式的使用;
- ⭐️ 掌握懒汉式单例模式的使用;
- ⭐️ 了解饿汉式与懒汉式单例模式的区别与优缺点。
本文来自专栏:JavaSE系列专题知识及项目 欢迎点击支持订阅专栏 ❤️
- 1 设计模式引入
- 2 单例模式
- 2.1 什么是单例模式
- 2.2 饿汉式单例模式
- 2.3 懒汉式单例模式
- 3 饿汉式与懒汉式的区别
- 写在最后
1 设计模式引入
🅰️ 什么是设计模式?
👩 答:我们可以把设计模式看成一局棋盘,英雄联盟云顶之弈大家玩过吧?对不同的英雄组合,我们需要不同的羁绊、不同的装备去针对性对付,才可以取得游戏胜利。而设计模式,就相当于一个固定的模板,当你遇到相同的状况时,可以直接免去思考直接使用。即,设计模式作为静态方法和属性的经典使用,是在大量实践中总结和理论之后优选的代码结构、编程风格、以及解决问题的思考方式。
2 单例模式 2.1 什么是单例模式
✈️ 所谓类的单例设计模式,就是 采用一定的方法保证在整个软件系统中,对某一个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
😎 这么说,小伙伴可能听不太明白,举个生活中的例子:我们每个人只能有一个女朋友,即只能有一个对象, 但是一般创建对象的方法无法保证我们只能 new
一个对象,比如下面的代码:
那么我们如何实现单例模式呢?目前,单例模式有两种实现方式:(1)饿汉式;(2)懒汉式
🍑 饿汉式单例模式实现步骤如下:
- 先将构造器私有化;
解释: 避免用户直接在外部new
新对象。 - 在类的内部 属性部分直接创建一个对象;
解释: 我们已经将构造器私有化了,因此在外部没有办法new
新对象,所以只能在类的内部创建对象。 - 向外 提供一个公共的静态方法,用于外部引用该对象。
解释: 创建好了对象后,如果对外不提供公共方法,我们就没有办法使用这个被创建的对象。
🍉 细节处理: 在类的外部,我们无法使用 new
新建对象,也就是说,我们只能通过 类名.xxx
的方式来返回创建的对象,因此,获取对象的对外公共方法需要使用 static
关键字修饰。而该方法中,需要返回类中创建的对象,静态方法只能使用静态变量,因此,对象属性也应当设置为 static
。
🍌 实现代码:
public class SingleTon {
public static void main(String[] args) {
// 创建对象
GirlFriend gf1 = GirlFriend.getInstance();
GirlFriend gf2 = GirlFriend.getInstance();
// 判断两对象是否为同一对象
System.out.println(gf1 == gf2); // true
}
}
class GirlFriend{
private String name;
// 在属性中直接创建对象, 为了静态方法能够返回该对象,因此需要设置为static
private static GirlFriend gf = new GirlFriend("毛毛虫");
// 构造方法私有化
private GirlFriend(String name){
this.name = name;
}
// 对外提供获取该对象的方法
public static GirlFriend getInstance(){
return gf;
}
}
🍎 实现结果:
true
你可能会问,gf1
和 gf2
不是两个对象吗?那为啥是 true
?这点可以回顾以下这篇博文(文章内的对象在内存中的存在形式部分):
❤️【JavaSE】深入理解类与对象 || 方法调用机制与方法的传参机制浅析
简单的解释一下,gf1
与 gf2
实际引用的是同一个堆空间,而这个堆空间在 new
的时候就确定了!具体见下图:(就是这么宠粉!🐕)
🍑 懒汉式单例模式实现步骤如下:
- 先将构造器私有化;
解释: 避免用户直接在外部new
新对象。 - 在类的内部 声明一个对象引用,但是不创建,即先不 new;
- 向外 提供一个公共的静态方法,用于创建对象并返回对象引用。
解释: 需要在该方法中创建对象,并返回给外部。
🍉 细节处理: 在类的外部,我们无法使用 new
新建对象,也就是说,我们只能通过 类名.xxx
的方式来返回创建的对象,因此,获取对象的对外公共方法需要使用 static
关键字修饰。而该方法中,需要返回类中创建的对象,静态方法只能使用静态变量,因此,对象属性也应当设置为 static
。(这点与饿汉式一致)
与饿汉式不同的是,我们需要在提供的公共方法中创建对象,需要在方法中确保创建的是同一对象,即当对象为 null 时创建,不为 null 时,直接返回上次创建的对象。
🍌 实现代码:
public class SingleTon {
public static void main(String[] args) {
// 创建对象
GirlFriend gf1 = GirlFriend.getInstance();
GirlFriend gf2 = GirlFriend.getInstance();
// 判断两对象是否为同一对象
System.out.println(gf1 == gf2); // true
}
}
class GirlFriend{
private String name;
// 在属性声明对象, 但是不创建
private static GirlFriend gf;
// 构造方法私有化, 防止直接new
private GirlFriend(String name){
this.name = name;
}
// 对外提供获取该对象的方法,如果对象还未创建,则先创建后返回
public static GirlFriend getInstance(){
if(gf == null){
gf = new GirlFriend("毛毛虫");
}
return gf;
}
}
🍎 实现结果:
3 饿汉式与懒汉式的区别true
Tips:文末有助记口令哦~~~
⭐️ Star 1: 两者最主要的区别是 在于创建对象的时机不同:饿汉式是在类加载的时候就创建了对象实例,而懒汉式是在使用时才创建(你不用我才懒得创建!)。
❤️类加载相关知识: 【JavaSE】学了这么久Java,你真的会用代码块吗?
(文章代码块使用细节中 star3 类何时被加载?)
⭐️ Star 2: 饿汉式不存在线程安全问题,而 懒汉式存在线程安全的问题。
解释: 请看如下代码块,方法 getInstance()
用于懒汉式单例模式,在使用时创建并返回对象,如果存在,则直接返回创建的对象。但是如果遇到短时间内多进程问题。比如:两个进程同时进入该方法,需要返回给 g1
,g2
对象实例。当 g1
进入该方法后,进行判断,不为 null
,因此创建一个对象,而在创建对象的过程中,g2
刚好也进入了该方法,也被判断成了不为 null
,此时,g1
, g2
就指向不同的对象了,所以它是线程不安全的。
// 对外提供获取该对象的方法,如果对象还未创建,则先创建后返回
public static GirlFriend getInstance(){
if(gf == null){
gf = new GirlFriend("毛毛虫");
}
return gf;
}
⭐️ Star 3: 饿汉式存在资源浪费的可能。 比如在程序中没有使用对象实例,那么饿汉式创建的对象就浪费了。请看如下代码:
public class SingleTon {
public static void main(String[] args) {
System.out.println(GirlFriend.age);
}
}
class GirlFriend{
static int age = 20;
private String name;
// 在属性中直接创建对象, 为了静态方法能够返回该对象,因此需要设置为static
private static GirlFriend gf = new GirlFriend("毛毛虫");
// 构造方法私有化
private GirlFriend(String name){
System.out.println("构造方法被调用,对象被创建");
this.name = name;
}
// 对外提供获取该对象的方法
public static GirlFriend getInstance(){
return gf;
}
}
🍎 在上述代码中,我们使用了 GirldFriend
类的静态成员 age
,但是我们并不需要创建一个对象。但是在该测试样例中,对象创建的构造方法却被调用了! 实现结果如下:
构造方法被调用,对象被创建
20
⭐️ Star 4: 在 JavaSE 的标准类中,java.lang.Runtime就是经典的单例模式。感兴趣的小伙伴们可以去查阅相应的源码,这里就暂时不赘述啦!!
📝 助记: 懒汉不关门,所以不安全;饿汉肚子空,吃饭废粮食!
写在最后
🌟以上便是本文的全部内容啦,后续内容将会持续免费更新,如果文章对你有所帮助,麻烦动动小手点个赞 + 关注,非常感谢 ❤️ ❤️ ❤️ !
如果有问题,欢迎私信或者评论区!
共勉:“你间歇性的努力和蒙混过日子,都是对之前努力的清零。”
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)