如何解决这个鸡蛋问题?

时间:2014-12-04 11:45:47

标签: java design-patterns reflection

我在这里看到了类似的问题,但是,我问这个问题基于this

我已经实现了接受的答案给出的建议,但是,我仍然看到正在创建两个实例。目标是我希望仅在特定方法调用上创建实例。我不能在Java 6的接口中使用静态方法。

我尝试过的代码

private static final Map<String, IRule> instancesMap = new Hashtable<String, IRule>();

@SuppressWarnings("unchecked")
public static <T extends IRule> T getRuleInstance(String clazz) {
    try {
        if (isInstanceCreated(clazz)) {
            T type = (T) instancesMap.get(clazz);
            if (logger.isDebugEnabled()) {
                logger.debug("Found a cashed instance of " + clazz + ". Returning " + type);
            }
            return type;
        } else {
            Class<?> ruleObject = Class.forName(clazz);
            Constructor<?> clazzConstructor = ruleObject.getDeclaredConstructor();
            /**
             * Hack encapsulation
             */
            clazzConstructor.setAccessible(true);
            IRule iRuleInstance = (IRule) clazzConstructor.newInstance();
            if (logger.isDebugEnabled()) {
                logger.debug("The instance of class " + clazz + " " + iRuleInstance + " has been created.");
            }
            instancesMap.put(clazz, iRuleInstance);
            return (T) iRuleInstance.getInstance();
        }
    } catch (ClassNotFoundException e) {
        logger.error("ClassNotFoundException", e);
    } catch (IllegalAccessException e) {
        logger.error("IllegalAccessException", e);
    } catch (SecurityException e) {
        logger.error("SecurityException", e);
    } catch (NoSuchMethodException e) {
        logger.error("NoSuchMethodException", e);
    } catch (IllegalArgumentException e) {
        logger.error("IllegalArgumentException", e);
    } catch (InvocationTargetException e) {
        logger.error("InvocationTargetException", e);
    } catch (InstantiationException e) {
        logger.error("InstantiationException", e);
    }
    return null;
}

private static boolean isInstanceCreated(String clazz) {
    return instancesMap.containsKey(clazz);
}

2 个答案:

答案 0 :(得分:1)

如果有缓存命中,则返回缓存的内容(instancesMap.get(clazz))。但如果没有命中,你缓存一件事(instancesMap.put(clazz, iRuleInstance))并返回另一件事(iRuleInstance.getInstance())。这没有意义。

添加到地图后不要致电getInstance,只需将其退回:

instancesMap.put(clazz, iRuleInstance);
return (T) iRuleInstance;

或者,调用getInstance,但缓存它:

(T) instance = iRuleInstance.getInstance();
instancesMap.put(clazz, instance);
return (T) instance;

无论哪种方式,你都必须返回你缓存的内容,以便它与你的缓存命中逻辑相匹配。

答案 1 :(得分:0)

您是否需要具备IRule的具体实现? - 您将从实施中使用哪些方法?它们不能被推广到界面本身吗?如果是这种情况,您可以使用Map<Class<? extends IRule>, IRule>地图来管理您的实例。