码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-09-10 19:49:16      阅读:135      评论:0      收藏:0      [点我收藏+]

标签: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 中。

 

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

标签:exce   child   static   extend   应用   hash   put   自己   方法   

原文地址:http://www.cnblogs.com/jing-an-feng-shao/p/7501767.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!