vendredi 18 novembre 2016

Single Instance Provider

I am trying to create a single instance provider class. I am able to work with the following code but I am stuck at the condition where I need a a new instance with primitive constructor arguments. One way is to check every possibility for example, for constructor(Integer arg0, int arg1) I need to check one of the following is present or not:

  • (Integer arg0, Integer arg1)
  • (Integer arg0, int arg1)
  • (int arg0, Integer arg1)
  • (int arg0, int arg1)

Is there another better way to do it?

public class InstanceProvider {

    static Map<InstanceModel, Object> instances = null;

    /**
     * Private constructor
     */
    private InstanceProvider() {

    }

    /**
     * Returns new instance of a class if not exist already
     * 
     * @param <T>
     * 
     * @param clazz
     *            class whose instance is needed
     * @param args
     *            class constructor parameters
     * @return instance of the class
     */
    @SuppressWarnings({ "unchecked" })
    public static <T> T getInstance(Class<T> clazz, Object... args) {

        T instance = null;
        InstanceModel instanceModel = new InstanceModel(clazz, args);
        Map<InstanceModel, Object> instanceMap = InstanceProvider.instances;
        if (instanceMap != null) {
            if (instanceMap.containsKey(instanceModel)) {
                return (T) instanceMap.get(instanceModel);
            }
        } else {
            InstanceProvider.instances = new HashMap<InstanceModel, Object>();
            instanceMap = InstanceProvider.instances;
        }
        try {
            Class<?>[] argClasses = new Class<?>[args.length];
            int index = 0;
            for (Object arg : args) {
                argClasses[index++] = arg.getClass();
            }
            instance = clazz.getDeclaredConstructor(argClasses).newInstance(args);
            instanceMap.put(instanceModel, instance);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return instance;
    }
}


public class InstanceModel {

    private Class<?> clazz;
    private Object[] args;

    /**
     * Constructor for Instancemodel
     * 
     * @param clazz
     *            class
     * @param args
     *            constructor arguments for the given class
     */
    public InstanceModel(Class<?> clazz, Object... args) throws NullPointerException {

        if (clazz == null) {
            throw new NullPointerException("Class name cannot be null");
        }
        this.clazz = clazz;
        this.args = args;
    }

    /**
     * Returns the class
     * 
     * @return
     */
    public Class<?> getClazz() {

        return clazz;
    }

    /**
     * Returns constructor arguments
     * 
     * @return
     */
    public Object[] getArgs() {

        return args;
    }

    /**
     * Check if two instancemodels are equal
     * 
     * @param model
     * @return
     */
    public boolean equals(Object o) {

        if (o instanceof InstanceModel) {
            InstanceModel model = (InstanceModel) o;
            if (!clazz.getName().equals(model.getClazz().getName())) {
                return false;
            }
            Object[] modelArgs = model.getArgs();
            if (args.length != modelArgs.length) {
                return false;
            }
            int index = 0;
            while (index < args.length) {
                if (!args[index].getClass().getName().equals(modelArgs[index].getClass().getName())) {
                    return false;
                }
                if (!args[index].equals(modelArgs[index])) {
                    return false;
                }
                index++;
            }
            return true;
        }

        return false;
    }

    /**
     * Returns hashcode for the object
     * 
     * @return hashcode
     */
    public int hashCode() {

        int hash = 0;
        int rem = 1000000007;
        hash = hash % rem + clazz.hashCode() % rem;
        for (Object arg : args) {
            hash = hash % rem + arg.hashCode() % rem;
        }

        return hash;
    }
}





Aucun commentaire:

Enregistrer un commentaire