单例模式
核心作用:
- 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
单例模式优点:
- 1,由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要 比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动 时直接产生一个单例对象,然后永久驻留内存的方式来解决。
- 2,单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计 一个单例类,负责所有数据表的映射处理。
常见的五种单例模式:
- 饿汉式(线程安全,调用效率高。但不能延时加载)
- 懒汉式(线程安全,调用效率不高,能够延时加载)
- 双重检测锁式(线程安全,能够延时加载)
- 静态内部类式(线程安全,调用效率高,可以延时加载)
- 枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式的实现:
public class Demo01 {
private static Demo01 instance = new Demo01();
private Demo01() {
}
public static Demo01 getInstance() {
return instance;
}
}
懒汉式的实现:
public class Demo02 {
private static Demo02 instance;
private Demo02() {
}
public synchronized static Demo02 getInstance() {
if(instance == null) {
instance = new Demo02();
}
return instance;
}
}
双重检测锁的实现:
public class Demo03 {
private static volatile Demo03 instance;
private Demo03() {};
public static Demo03 getInstance() {
if(instance == null) {
synchronized(Demo03.class) {
if(instance == null) {
instance = new Demo03();
}
}
}
return instance;
}
}
静态内部类式的实现:
public class Demo04 {
private static class SingleClass{
private static final Demo04 Instance = new Demo04();
}
private Demo04() {
}
public static Demo04 getInstance() {
return SingleClass.Instance;
}
}
枚举单例的实现:
public enum Demo05 {
INSTANCE;
}
防止反射和反序列化破坏单例模式
- 以饿汉式为例:
- 为防止反射调用构造器创建对象,我们需要在构造器中加入对instance的判断,若存在则返回错误。
- 而readReslove则是防止反序列化破坏单例,当反序列化时,若存在readReslove方法时,则调用该方法。
package SingleInstance;
public class Demo06 {
private static Demo06 instance = new Demo06();
private Demo06() {
if(instance != null) {
throw new RuntimeException("单例不允许重复创建对象");
}
}
public static Demo06 getInstance() {
return instance;
}
private Object readReslove(){
return instance;
}
}