提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
JAVA八股设计模式之单例模式。
提示:以下是本篇文章正文内容,下面案例可供参考
一、单例模式是什么??
单例模式是最简单的设计模式,也在原子听闻的,看到的资料中说是面试中最常问的一种设计模式。正好学校也在选秀刘伟大大的设计模式一书,所以就结合书和资料在附上我的理解进行第二次创新总结咯!
定义
单例模式确保某一个类只有一个实例,并且自行实例化并向整个系统提供这一个实例(对象)。(会在堆内存中只创建一个对象的设计模式)
二、简单例子
假如全天下的单身狗都是一样的,我们在程序中运行SingleDog对象,并将成员变量和构造方法等设置为静态,是否可以保证在图中有且仅有一个实例呢?(就是不管你new几个对象出来,但是都是在堆中共享同一个地址+
)
代码演示
静态建立SingleDog使其确保在堆创建唯一的实例,然后再用户测试类中建造两个SingleDog对象,可以看到使用String类型的“==”比较结果为ture(j具体是为什么可以观看上一篇),所以证明创建的两个对象再堆中指向的对象相同。
package com.aoyuanhomeword.danli;
public class SingleDog {
public static SingleDog singleDog = null;
private SingleDog(){}
public static SingleDog getSingleDog(){
if (singleDog == null)
singleDog = new SingleDog();
return singleDog;
}
}
public class SingleDogClient {
public static void main(String[] args) {
SingleDog singleDog = SingleDog.singleDog;
SingleDog singleDog2 = SingleDog.singleDog;
System.out.println(singleDog == singleDog2);
}
}
单例模式的分类
再单例模式中有两种类型分别是
懒汉式单例模式:在真正需要使用对象时才去创建该单例类对象(我感觉就是再成员变量那边后面使用不使用new等等)
饿汉式单例模式: 在类加载的时候直接创建,不需要等到使用对象的时候才去创建对象。
这两个类型的区别其实十分明显(只要你愿意在程序中使用代码去自己跑一跑)
懒汉式单例模式
public class Singleton {
//记住这里!!!!!!!!!!!!!!!!!!!!
// 私有静态变量instance,用于保存唯一的实例
private static Singleton instance;
//记住这里为止!!!!!!!!!!!!!!!!!!!!!
// 私有构造函数,防止外部类实例化
private Singleton() {}
// 公有静态方法,用于获取单例实例
public static Singleton getInstance() {
// 如果实例尚未初始化,则创建一个新实
if (instance == null) {
//可以看到这里才会创建对象
instance = new Singleton();
}
// 返回单例实例
return instance;
}
}
public class SingletonTest {
public static void main(String[] args) {
// 获取单例实例
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
// 检查两个实例是否相同
if (instance1 == instance2) {
System.out.println("两个实例是相同的,是单例模式的实例。");
} else {
System.out.println("两个实例不同,单例模式未正确实现。");
}
}
}
```java
```java
package com.aoyuanhomeword.danli;
public class Singleton {
private static Singleton instance;
// 私有构造函数,防止外部类实例化
private Singleton() {}
// 公有静态方法,用于获取单例实例
public static Singleton getInstance() {
// 如果实例尚未初始化,则创建一个新实例
if (instance == null) {
instance = new Singleton();
}
// 返回单例实例
return instance;
}
}
class SingletonTest {
public static void main(String[] args) {
// 记录开始时间
long startTime = System.nanoTime();
// 获取单例实例
Singleton instance = Singleton.getInstance();
// 记录结束时间
long endTime = System.nanoTime();
// 计算并打印加载和创建对象所需的时间
long elapsedTime = endTime - startTime;
System.out.println("类加载到创建对象完成所需的时间(纳秒): " + elapsedTime);//类加载到创建对象完成所需的时间
//(纳秒): 816400
}
}
饿汉式单例模式
package com.aoyuanhomeword.danli;
public class Singleton {
//看到了把,和上面的比一比把!!!!!!!!!!!!!!!
// 在类加载时就创建实例
private static final com.aoyuanhomeword.danli.Singleton instance = new com.aoyuanhomeword.danli.Singleton();
// 私有构造函数,防止外部类实例化
private Singleton() {}
// 公有静态方法,用于获取单例实例
public static com.aoyuanhomeword.danli.Singleton getInstance() {
return instance;
}
}
class SingletonTest {
public static void main(String[] args) {
// 记录开始时间
long startTime = System.nanoTime();
// 获取单例实例
com.aoyuanhomeword.danli.Singleton instance = com.aoyuanhomeword.danli.Singleton.getInstance();
// 记录结束时间
long endTime = System.nanoTime();
// 计算并打印加载和创建对象所需的时间
long elapsedTime = endTime - startTime;
System.out.println("类加载到创建对象完成所需的时间(纳秒): " + elapsedTime);//807777
}
}
总结
在饿汉式和懒汉式单例模式中,从类加载到创建对象完成的时间来看,饿汉式单例模式通常会更快。
原因是,在饿汉式单例模式中,实例在类加载时就已经被创建好了,因此在获取实例时只需返回已经存在的实例,不需要进行额外的判断和同步操作。而在懒汉式单例模式中,实例的创建是在第一次调用 getInstance() 方法时才进行的,因此在获取实例时需要进行额外的判断,以确保只创建一个实例,并进行同步操作以确保线程安全。
由于饿汉式单例模式在类加载时就创建了实例,因此在第一次获取实例时,它的性能可能会更好一些,而懒汉式单例模式在第一次获取实例时可能会稍微慢一些,因为需要进行额外的判断和同步操作。但在后续获取实例时,两者的性能差异可能会变得很小,因为已经创建好了实例,不需要再次创建。
总的来说,如果您更关注初始化时的性能,饿汉式单例模式可能更适合;如果您更关注延迟加载和节省资源,懒汉式单例模式可能更适合。
但是,反射和序列化,它们俩都可以把单例对象破坏。