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