单例模式
保证一个类有且仅有一个实例,并提供一个全局访问点,实现思路如下:
- 私有化构造方法,
private Singleton()
- 静态属性来保存唯一实例,
private static final Singleton instance
- 静态方法来获取唯一实例,
getInstance()
/**
* @description: Singleton,最简单的实现
* @author: lsrong
* @date: 2022/9/30 17:25
**/
public class Singleton {
// 私有构造
private Singleton(){}
// 私有唯一实例
private static final Singleton instance = new Singleton();
// 公开实例获得方法
public static Singleton getInstance(){
return instance;
}
}
上面需要注意不应该在Singleton类中塞入其他的静态方法,还有这种方法每次都会生成实例对象,有些情况是不需要生成的,这种情况称为延迟加载,实现方式如下:
/**
* @description: DeferSingleton,延迟加载单例模式
* @author: lsrong
* @date: 2022/9/30 17:25
**/
public class DeferSingleton {
// 私有构造
private DeferSingleton(){}
// 私有唯一实例
private static volatile DeferSingleton instance;
// 延迟加载
public static DeferSingleton getInstance(){
if(instance == null){
synchronized (DeferSingleton.class){
if(instance == null) {
instance = new DeferSingleton();
}
}
}
return instance;
}
}
多线程下会出现并发的问题,因此需要加锁synchronized
,一旦加锁就会严重影响性能,所以一般不会用这种方式。
嵌套类的方式也可以实现,和简单的单例模式类似:
/**
* @description: 嵌套类的单例模式
* @author: lsrong
* @date: 2022/9/30 17:40
**/
public class HolderSingleton {
private HolderSingleton(){}
// 嵌套类可以访问外部类的静态属性和静态方法 的特性
private static class Holder{
private static HolderSingleton instance = new HolderSingleton();
}
public static HolderSingleton getInstance(){
return Holder.instance;
}
}
另一种实现Singleton的方式是利用Java的enum
,因为Java保证枚举类的每个枚举都是单例,所以我们只需要编写一个只有一个枚举的类
/**
* @description: 枚举类的单例模式
* @author: lsrong
* @date: 2022/9/30 17:48
**/
public enum EnumSingleton {
INSTANCE; // 唯一枚举
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
// 使用
// String name = World.INSTANCE.getName();
实际上,大部分框架都有提供实例化单例类的方式,如Spring的Component
:
@Component // 表示一个单例组件
public class MyService {
...
}