0
点赞
收藏
分享

微信扫一扫

设计模式-单例模式

凯约 2022-02-08 阅读 217

单列模式的定义:

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池,缓存,日志对象,对话框等常被设计成单例

单例模式的特点:

1.单例类智能有一个实例.

2.单例类必须自己创建自己的唯一实例.

3.单例类必须给其他对象提供这一实例.

实现单列的5种方式

懒汉式:默认不会实例化,第一次使用的时候实例化.(可能会由有线程安全问题)

1. 双重检查,已解决线程安全问题【推荐使用】

public class Singleton4 {

    private static volatile Singleton4 singleton;

    private Singleton4() {
    }

    public static Singleton4 getInstance() {
        if (singleton == null) {
            synchronized (Singleton4.class) {
                if (singleton == null) {
                    singleton = new Singleton4();
                }
            }
        }
        return singleton;
    }
}

2.静态内部类  【推荐使用】

public class Singleton5 {
    
    private Singleton5() {
    }

    // 静态内部类
    public static class Singleton5Instance {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    public static Singleton5 getInstance() {
        return Singleton5Instance.INSTANCE;
    }
}

饿汉式 : 默认实例化 (类加载的时候实例化 无线程安全问题)

1.静态常量【可用】

public class Singleton {

    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

2.静态代码块【可用】

public class Singleton2 {
  
    private static Singleton2 INSTANCE;

    private Singleton2() { }

    static {
        INSTANCE = new Singleton2();
    }

    public static Singleton2 getInstance() {
        return INSTANCE;
    }
}

 3.枚举【推荐使用】

public class Singleton6 {

    public Singleton6() {
    }

    public static Singleton6 getInstance() {
        return SingletonEnum.INSTANCE.getSingleton();
    }

    private enum SingletonEnum {

        INSTANCE;

        private Singleton6 singleton;

        SingletonEnum() {
            singleton = new Singleton6();
        }

        private Singleton6 getSingleton() {
            return singleton;
        }
    }
}

 单例模式的破坏以及解决办法 (反射/反序列化)

 除枚举外,其他的方法都可以通过反射的方式破坏单例模式 反射是通过调用构造方法生成新的对象,如果想要阻止单例被破坏,可以在构造方法中进行判断.

 private Singleton4() {
        if (singleton != null) {
            throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
        }
 }

如果单例类实现了Serializable, 就可以通过反序列化破坏单例.解决办法是在单例类中添加反序列化方法readResolve

public class Singleton5 {

    private Singleton5() {
    }

    // 静态内部类
    public static class Singleton5Instance {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    public static Singleton5 getInstance() {
        return Singleton5Instance.INSTANCE;
    }

    // 防止反序列化破坏单例模式
    public Object readResolve() {
        return Singleton5Instance.INSTANCE;
    }
}

添加readResolve 方法,方法中返回实例的逻辑与单例类提供的获取实例的逻辑一模一样.

举报

相关推荐

0 条评论