• 设计模式(一)单例模式:6-登记模式


    思想:

      登记模式,和前面5种单例不一样,从本质上来说,这是一种兼顾创建和管理单例的方法。 

      主要实现步骤是:

    • 所有单例都继承于一个共同的父类。
    • 子类通过父类完成单例的创建,父类使用反射创建子类。
    • 父类持有一个 String-Object 的数据模型去存储创建出来的单例对象,一般称为 Registry。
    • 第二次,及之后需要获取单例对象时,直接从 Registry 中获取。
    public class RegisterSingleton {
    
        protected RegisterSingleton() {
    
        }
    
        protected static final Map<String, RegisterSingleton> registry = new HashMap<>();
        private static final String name;
    
        private static volatile Object lock = new Object();
    
        static {
            RegisterSingleton registerSingleton = new RegisterSingleton();
            name = registerSingleton.getClass().getName();
            registry.put(name, registerSingleton);
        }
    
        public static RegisterSingleton getInstance(String keyName) {
            if (keyName == null) {
                keyName = RegisterSingleton.name;
            } else if (registry.get(keyName) == null) {
                try {
                    synchronized (lock) {
                        Class<?> clazz = Class.forName(keyName);
                        Constructor<?> constructor = clazz.getDeclaredConstructor();
                        constructor.setAccessible(true);
                        RegisterSingleton singleton = (RegisterSingleton) constructor.newInstance();
                        registry.put(keyName, singleton);
                    }
                } catch (Exception e) {
                    throw new IllegalArgumentException();
                }
            }
            return registry.get(keyName);
        }
    
    }
    public final class RegisterSingletonChild extends RegisterSingleton {
    
        private static final String keyName = RegisterSingletonChild.class.getName();
    
        private RegisterSingletonChild() {
            if (registry.get(keyName) != null) {
                throw new IllegalStateException();
            }
        }
    
        public static RegisterSingletonChild getInstance() {
            return (RegisterSingletonChild) RegisterSingleton.getInstance(keyName);
        }
    
        public static void destroyInstance() {
            registry.remove(keyName);
        }
    }
    • 反射?

      这一点和 LazySingleton 的情况是一致的,反射是否能够打破单例取决于反射和 getInstance() 方法的调用顺序。

    • 多线程? 

      在第一次创建对象时,进行了加锁的控制,保证了单例。

    • 优势?劣势?

      优势:达到了管理单例的效果,这个特点在很多框架中都有体现。例如,用 Spring IoC 创建的单例对象,都会放到一个 registry 里面。

      劣势:对创建的单例有继承关系的要求;创建单例时使用了反射。

  • 相关阅读:
    单调栈
    P1164 小A点菜
    P1156 垃圾陷阱
    P1140 相似基因
    P1136 迎接仪式
    P1133 教主的花园
    P1131 [ZJOI2007]时态同步
    P1130 红牌
    利用SQLite在android上实现增删改查
    利用SQLite在android上创建数据库
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/7501767.html
Copyright © 2020-2023  润新知