zoukankan      html  css  js  c++  java
  • 作业18:单例模式

    一 什么是单例?

    顾名思义就是单个实例

    当你开出来的摸具,并使用摸具产生唯一一个模型,这就是单例。

    而单例模式就是为了保证该类只产生一个实例。

    二 什么时候需要单例?

    简单说,你不需要多个实例的时候,就可以使用单例。

    工具类一般都定义为单例,因为工具类不需要那么多个实例。

    单例的好处:

    • 节省维护对象的开销:创建、内存占用、回收
    • 实例状态易于维护,注:一般单例不维护状态,当多个线程进行更改状态时,会产生并发问题。

    三 如何实现单例?(不考虑序列化、反射)

    1 饿汉式

    public class Singleton{
        private static final Singleton instance = new Singleton();
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    2 懒汉式

    public class Singleton {
        private static Singleton instance;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    3 静态内部类

    public class Singleton {
        private Singleton() {}
    
        public static Singleton getInstance() {
            return SingletonHolder.instance;
        }
    
        static class SingletonHolder {
            private static final Singleton instance = new Singleton3();
        }
    }
    

    4 枚举

    public enum  Singleton {
        instance;
    }
    

    注:枚举本质上就是饿汉模式,具体参考作业16:java枚举类的秘密

    四 单例补充

    1 考虑反射

    • 暴力反射能打破private限制,从而调用构造方法来创建对象。
    public class Main {
        public static void main(String[] args) throws Exception{
            Class<? extends Singleton> aClass = Singleton.getClass();
            Constructor<? extends Singleton> constructor = aClass.getDeclaredConstructor();
            constructor.setAccessible(true); // 暴力反射
            Singleton singleton = constructor.newInstance();
            System.out.println(singleton == Singleton.getInstance()); // false
        }
    }
    
    // 以饿汉为例的解决方案:构造器中抛出异常,防止对象创建成功
    public class Singleton{
        private static final Singleton instance = new Singleton();
    
        private Singleton() {
            if (instance != null)
                throw new RuntimeException("private constructor");
        }
    
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    2 考虑序列化

    public class Main {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // 序列化
            ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("singleton.txt")));
            oo.writeObject(Singleton.getInstance());
            oo.close();
    
            // 反序列化
            ObjectInputStream oi = new ObjectInputStream(new FileInputStream(new File("singleton.txt")));
            Singleton singleton = (Singleton) oi.readObject();
            oi.close();
    
            System.out.println(singleton == Singleton.getInstance()); // false
        }
    }
    
    // 以饿汉为例的解决方案:添加readResolve方法
    public class Singleton implements Serializable {
        private static final Singleton instance = new Singleton();
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            return instance;
        }
    
        private Object readResolve() {
            return instance;
        }
    }
    

    参考资料:

  • 相关阅读:
    《操作系统实现之路》前言及内容提要
    《操作系统实现之路》源代码下载路径及求助途径
    电影《泰囧》中的一个穿帮漏洞
    Android中级第六讲相机对焦功能实现
    对《移动互联网白皮书(2013年)》的几个解读
    中国将自主研发操作系统对抗谷歌
    Android高级开发第八讲粗略讲述Java之软引用、弱引用和虚引用
    WP7 App性能优化(5):加快应用程序启动速度(下)
    WP7 App性能优化(6):理解线程
    Windows Phone 7 第3方控件集概览
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/10563606.html
Copyright © 2011-2022 走看看