单例模式

定义

一个类只有一个实例,该实例必须自行创建,并且向整个系统提供这个实例

实现考虑因素

  • 唯一性
    • 是否防克隆
    • 是否防反射
    • 是否防序列化
  • 性能
    • 是否需要懒加载
    • 是否防指令重排(双重锁方式问题)

三种实现方式

实现 懒加载 线程安全 防克隆 防反射 防序列化
双重锁
静态内部类
枚举

双重锁方式(添加了防御功能)

public class Singleton implements Serializable, Cloneable {

    private static volatile Singleton sSingleton; // volatile防止指令重排
    private static boolean sFlag = true;
    private Singleton() {
        if(sFlag){ // 防反射
            sFlag = false;
        }else{
            throw new RuntimeException("对象已经存在");
        }
    }

    public static Singleton getSingleton() {
        if (sSingleton == null) {
            synchronized (Singleton.class) {
                if (sSingleton == null) {
                    sSingleton = new Singleton();
                }
            }
        }
        return sSingleton;
    }

    private Object readResolve() {
        return getSingleton(); // 防序列化
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return getSingleton(); // 防克隆
    }
}

静态内部类方式

public class Instance {
    private Instance() {
    }

    private static class Holder {
        // 类加载机制保证懒加载,static&final确保线程安全
        private static final Instance INSTANCE = new Instance();
    }

    public static Instance getInstance() {
        return Holder.INSTANCE;
    }

}

枚举类方式

public enum Single {
    SINGLE;
    public void whateverMethod(){
    }
}

基本等价于(除enum的防反射、序列化、克隆等属性)

public final class Single{
    public static final Single SINGLE = new Single();
}

测试代码

 public static void main(String args[]) {

        try {
            Singleton singleton = Singleton.getSingleton();
            testCloneSingleton(singleton);
            testReflectSingleton(singleton);
            testSerializableSingleton(singleton);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testCloneSingleton(Singleton singleton) throws CloneNotSupportedException {

        boolean equals = singleton.equals(Singleton.getSingleton().clone());

        System.out.print(equals);
    }

    private static void testReflectSingleton(Singleton singleton) throws Exception {
        Constructor constructor = Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        constructor.newInstance();

        boolean equals = singleton.equals(constructor.newInstance(););

        System.out.print(equals);

    }

    private static void testSerializableSingleton(Singleton singleton) throws Exception {
        String tempFile = "tempFile";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tempFile));
        oos.writeObject(getSingleton());
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File(tempFile)));

        boolean equals = singleton.equals(objectInputStream.readObject());

        System.out.print(equals);

    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.单例模式概述 (1)引言 单例模式是应用最广的模式之一,也是23种设计模式中最基本的一个。本文旨在总结通过Ja...
    曹丰斌阅读 8,059评论 6 47
  • 单例模式(SingletonPattern)一般被认为是最简单、最易理解的设计模式,也因为它的简洁易懂,是项目中最...
    成热了阅读 9,734评论 4 34
  • 主要参考自 菜鸟教程 单例模式是JAVA中最简单的模式之一,这种模式属于创建型模式,它提供了一种创建对象的最...
    东溪95阅读 3,555评论 0 2
  • 前言 本文主要参考 那些年,我们一起写过的“单例模式”。 何为单例模式? 顾名思义,单例模式就是保证一个类仅有一个...
    tandeneck阅读 7,216评论 1 8
  • 单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间;能够避免...
    修罗掌柜阅读 4,216评论 0 3