根据单例实例构造的时机和方式不同,单例模式还可以分成几种,但对于这种通过私有化构造函数,静态方法提供实例的单例类而言,是不支持继承的。这种模式的单例实现要求每个具体的单例类自身来维护单例实例和限制多个实例的生成。可以采用另外一种实现单例的思路:登记式单例,来使得单例对继承开放。
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; public abstract class AbstractSingleton { private static Map<String, AbstractSingleton> registryMap = new HashMap<String, AbstractSingleton>(); AbstractSingleton() throws SingletonException{ String clazzName = this.getClass().getName(); if (registryMap.containsKey(clazzName)){ throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!"); } else { synchronized(registryMap){ if (registryMap.containsKey(clazzName)){ throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!"); } else { registryMap.put(clazzName, this); } } } } @SuppressWarnings("unchecked") public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz) throws InstantiationException, IllegalAccessException{ String clazzName = clazz.getName(); if(!registryMap.containsKey(clazzName)){ synchronized(registryMap){ if(!registryMap.containsKey(clazzName)){ T instance = clazz.newInstance(); return instance; } } } return (T) registryMap.get(clazzName); } public static AbstractSingleton getInstance(final String clazzName) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ if(!registryMap.containsKey(clazzName)){ Class<? extends AbstractSingleton> clazz = Class.forName(clazzName).asSubclass(AbstractSingleton.class); synchronized(registryMap){ if(!registryMap.containsKey(clazzName)){ AbstractSingleton instance = clazz.newInstance(); return instance; } } } return registryMap.get(clazzName); } @SuppressWarnings("unchecked") public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz, Class<?>[] parameterTypes, Object[] initargs) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, InstantiationException, IllegalAccessException{ String clazzName = clazz.getName(); if(!registryMap.containsKey(clazzName)){ synchronized(registryMap){ if(!registryMap.containsKey(clazzName)){ Constructor<T> constructor = clazz.getConstructor(parameterTypes); T instance = constructor.newInstance(initargs); return instance; } } } return (T) registryMap.get(clazzName); } static class SingletonException extends Exception { /** * */ private static final long serialVersionUID = -8633183690442262445L; private SingletonException(String message){ super(message); } } }
以上代码实现了一个抽象类,该类使用一个静态的Map来维护各个子类的实例。在构造方法中判断对应子类的实例是否已登记,若已登记则抛出一个SingletonException阻止实例的创建。由于构造子类的实例必须先执行父类的构造方法,因此子类第一次通过构造方法创建对象时,父类构造方法会自动把实例登记,以后再调用该子类的构造方法则会抛出异常,即便子类构造方法是public的,也只能成功创建一个实例。同时父类提供几个getInstance方法,通过传入需要获取实例的子类Class对象或Class限定名来获取对应的实例。前两个方法需要子类提供无参构造方法,第三个getInstance方法提供子类只有有参构造方法的情况下,通过参数构造子类对象。下面给出两个具体实现类的例子:
public class ConcreteSingleton1 extends AbstractSingleton { public ConcreteSingleton1() throws SingletonException { super(); // TODO Auto-generated constructor stub } public static ConcreteSingleton1 getInstance(){ try { return AbstractSingleton.getInstance(ConcreteSingleton1.class); } catch (InstantiationException e) { // TODO Auto-generated catch block // will not happen e.printStackTrace(); return null; } catch (IllegalAccessException e) { // TODO Auto-generated catch block // will not happen e.printStackTrace(); return null; } } } public class ConcreteSingleton2 extends AbstractSingleton { private final int value; public ConcreteSingleton2(int value) throws SingletonException { super(); // TODO Auto-generated constructor stub this.value = value; } public static ConcreteSingleton2 getInstance(int value){ try { return AbstractSingleton.getInstance(ConcreteSingleton2.class, new Class<?>[]{int.class}, new Object[]{value}); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public int getValue(){ return value; } }
原文出处:
http://www.cnblogs.com/wang9192/p/3975748.html