标签:exce child static extend 应用 hash put 自己 方法
思想:
在之前说到单元素枚举类,有提及到继承的情况。
说起单例模式,不管是什么方法实现的,有一点共性是不变的:不对外提供构造器,即将构造器的权限设为 private。
在一般情况下,以上方法是通用的,但是如果考虑到这个类的结构可能很复杂,会抽象出一个父类出来(不是指抽象类),那么如果这个父类也要保持单例,那么就不能将父类的构造器的权限设为 private 了。
这时,要保证做到以下两点:一个良好包结构设计 && 一个 protected 的构造器。
登记模式,是指所有的子类,都统一通过父类去构造,将自己的单例,存储在父类中。
相比于之前5种方式,更加倾向于构造单例,这种模式,重点在于管理单例。
1 public class RegisterSingleton { 2 3 protected RegisterSingleton() { 4 5 } 6 7 private static final Map<String, RegisterSingleton> registry = new HashMap<>(); 8 private static final String name; 9 10 private static volatile Object lock; 11 12 static { 13 RegisterSingleton registerSingleton = new RegisterSingleton(); 14 name = registerSingleton.getClass().getName(); 15 registry.put(name, registerSingleton); 16 } 17 18 public static RegisterSingleton getInstance(String name) { 19 if (name == null) { 20 name = RegisterSingleton.name; 21 } else if (registry.get(name) == null) { 22 try { 23 synchronized (lock) { 24 Class<?> clazz = Class.forName(name); 25 Constructor<?> constructor = clazz.getDeclaredConstructor(); 26 constructor.setAccessible(true); 27 RegisterSingleton singleton = (RegisterSingleton) constructor.newInstance(); 28 registry.put(name, singleton); 29 } 30 } catch (Exception e) { 31 throw new IllegalArgumentException(); 32 } 33 } 34 return registry.get(name); 35 } 36 37 }
1 public final class RegisterSingletonChild extends RegisterSingleton { 2 3 private RegisterSingletonChild() { 4 5 } 6 7 public static RegisterSingletonChild getInstance() { 8 return (RegisterSingletonChild) RegisterSingleton.getInstance(RegisterSingletonChild.class.getName()); 9 } 10 11 }
分析:
由于所有的构造,都是通过反射来实现的,那么显然,反射可以很轻松地打破单例。
父类首先在自身的静态代码块,完成对自己的初始化。
父类存有一个 String-Object 结构的键值对,其中 key 为单例类的完整类名,显然这是唯一的,这个存放单例的容器,一般称之为 Registry。
通过调用子类提供的 getInstance() 方法,间接调用父类的 getInstance(String) 方法,如果是第一次调用,通过反射进行单例的创建;否则,可以直接从 Registry 中取出。
多线程只需要在初始化子类对象的时候考虑即可,使用 DCL 双锁检测机制。
应用:
这种登记模式,如果研究过 Spring IOC 源码实现的朋友们,会有种似曾相识的感觉。
其实 Spring IOC 管理的类,最终都会被放到一个以 Registry 结尾的类中,一个 String-Object 结构的 Map 中。
标签:exce child static extend 应用 hash put 自己 方法
原文地址:http://www.cnblogs.com/jing-an-feng-shao/p/7501767.html