A generic cache object

Posted on

Problem

I have a “generic” cache object:

public class Cache {

    private static final Map<Class, ICacheable> cacheMap = new HashMap<>();

    public static ICacheable getCacheableElement(Class cacheableElementClass, Object... params) {
        ICacheable cacheableElement = cacheMap.get(cacheableElementClass);
        if (cacheableElement == null) {
            cacheableElement = addIfNotExists(cacheableElementClass, params);
        }
        return cacheableElement;
    }

    private static ICacheable addIfNotExists(Class cacheableElementClass, Object... params) {
        ICacheable cacheableElementAdded;

        if (cacheableElementClass.equals(SourceCode.class)) {
            cacheMap.put(cacheableElementClass, new SourceCode((String) params[0]));
        } else if (cacheableElementClass.equals(SymbolTable.class)) {
            cacheMap.put(cacheableElementClass, new SymbolTable());
        } else {
            // Error!
            throw new NullPointerException();
        }
        cacheableElementAdded = cacheMap.get(cacheableElementClass);
        return cacheableElementAdded;
    }
}

The Cache‘s responsibility is cache any kind of object. For that reason, I have the method’s param params (I need to find a better name). params is for those objects which need a param for its creation. For example:

public class SourceCode implements ICacheable {

    private String sourceCode;
    public static final Character EOF = '#';

    public SourceCode(String sourceCode) {
        this.sourceCode = sourceCode.toUpperCase() + EOF;
    }
}

As you can see, SourceCode needs a String param (sourceCode) for its creation.

In some part of the code, I fill the cacheMap… In the case of the SourceCode:

cacheMap.put(cacheableElementClass, new SourceCode((String) params[0]));

Here is my problem. As you can see, I create the SourceCode object with the first element of params array (remember the varargs in the above method’s signature). IMHO, this is not a clean solution, because some objects will use the params array (SourceCode), and others won’t use it.

Is there a design pattern or a better way to refactoring this?


EDIT: This is the solution I created:
enter image description here

As you can see, each object will have its own cache object (implementing ICache interface). Also,I have a CacheFactory which responsibility is create the cache object and returning it if it was already created.

Here is the code:

ICache:

public interface ICache {

    public Object getCacheableElement(Object... params);
}

CacheFactory

public class CacheFactory {

private static final Map<Class<?>, ICache> caches = new HashMap<>();

public static ICache createCache(Class cacheClass) {
Boolean isICacheType = isICacheType(cacheClass);

if (isICacheType) {
if (caches.containsKey(cacheClass)) {
return caches.get(cacheClass);
} else {
try {
ICache cache = (ICache) cacheClass.getConstructor().newInstance();
caches.put(cacheClass, cache);
return cache;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
// TODO: Is this safe? If not, FIX IT!
System.err.println(ex.getMessage());
throw new NullPointerException();
}
}
} else {
throw new IllegalArgumentException(String.format("Class "%s"" not supported yet."",

Solution

Leave a Reply

Your email address will not be published. Required fields are marked *