1.什么是单例模式
单例模式是指,只创建一个类的实例,这个类提供了唯一一种访问这个实例的方式。
2.单例模式的特点
- 单例类只有一个实例
- 单例类的实例定义在类内,由该类提供访问方式
- 单例类的构造函数必须是私有的(私有构造函数只能在类内部被调用)
3.实现单例模式的逻辑
将类的唯一实例作为类的私有静态成员变量封装在类内,并提供访问实例的公有方法,通过类名.方法名()调用
4.单例模式的两种形式
- 饿汉式:在类加载时(JVM虚拟机执行.class文件)生成类的实例
- 懒汉式:在首次使用该实例时在生成
5.饿汉式
两种实现方法
- 用静态成员变量创建类的实例
- 用静态代码创建类的实例
5.1静态成员变量创建类的实例
需要声明一个私有的静态成员变量并赋值,然后对外暴露出可以公共访问的方式,记得一定要把构造方法私有化
public class Singleton1 {
private String name;
private int age;
private String ID;
private static Singleton1 instance = new Singleton1();//静态成员变量instance作为类的实例
private Singleton1(){
this.age=21;
this.ID="202203180031";
this.name="Theshy";
};
public static Singleton1 getInstance() {
return instance;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public String getID(){
return ID;
}
}
public class Main {
public static void main(String[] args) {
Singleton1 ton1 = Singleton1.getInstance();
System.out.println(ton1.getAge());
System.out.println(ton1.getName());
System.out.println(ton1.getID());
}
}
5.2在静态代码块中创建类的实例
用静态代码块中创建对象,顾名思义,就是在静态代码块中给对象赋值,首先,我们一样要将构造方法私有化,然后在成员变量中声明一个该类的对象,在静态代码块中给对象赋值,最后,只有对外暴露出公共的访问方式即可。
public class Singleton1 {
private static Singleton1 instance //静态成员变量instance作为类的实例
public static Singleton1 getInstance() {
instance = new Singleton1() //在静态代码块中赋值
return instance;
}
}
6.懒汉式
构造函数私有化,在对外暴露的公有函数中创建对象,创建时先判断对象是否被赋值了,若赋值则直接返回,若为未赋值则赋值创建实例
public class Singleton1 {
private static Singleton1 instance //静态成员变量instance作为类的实例
private Singleton1(){};
public static Singleton1 getInstance() {
if(instance == null){
instance = new Singleton1() //在静态代码块中赋值
}
return instance;
}
}
实际上这种做法是存在问题的,从上面代码我们可以看出该方式在成员位置声明Singleton3类型的静态变量,并没有进行对象的赋值操作,那么什么时候赋值的呢?当调用getInstance()方法获取Singleton3类的对象的时候才创建Singleton3类的对象,这样就实现了懒加载的效果。但是,如果是多线程环境,会出现线程安全问题。
7.加锁
7.1为公有的暴露方式加锁
private static Singleton1 instance //静态成员变量instance作为类的实例
private Singleton1(){};
public static synchronized Singleton1 getInstance() {
if(instance == null){
instance = new Singleton1() //在静态代码块中赋值
}
return instance;
}