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;
        }
    }
    

    参考资料:

  • 相关阅读:
    如何只通过Sandboxed Solution启动一个定时执行的操作
    创建与SharePoint 2010风格一致的下拉菜单 (续) 整合Feature Custom Action框架
    创建与SharePoint 2010风格一致的下拉菜单
    《SharePoint 2010 应用程序开发指南》第二章预览
    SharePoint 2013 App 开发 (1) 什么是SharePoint App?
    使用Jscex增强SharePoint 2010 JavaScript Client Object Model (JSOM)
    搜索范围的管理
    SharePoint 2010 服务应用程序(Service Application)架构(1)
    SharePoint 2010 服务应用程序(Service Application)架构(2)
    SharePoint 2013 App 开发 (2) 建立开发环境
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/10563606.html
Copyright © 2011-2022 走看看