有没有办法使用某种通用方法来统一以下类似的方法?
public ClassA getInstanceA(String key)
{
if (instanceAMap.contains(key))
{
return instanceAMap.get(key);
}
ClassA result = new ClassA();
instanceAMap.put(key, result);
return result;
}
public ClassB getInstanceB(String key)
{
if (instanceBMap.contains(key))
{
return instanceBMap.get(key);
}
ClassB result = new ClassB();
instanceBMap.put(key, result);
return result;
}
public ClassC getInstanceC(String key)
{
if (instanceCMap.contains(key))
{
return instanceCMap.get(key);
}
ClassC result = new ClassC();
instanceCMap.put(key, result);
return result;
}
所以,我想对所有类只有一种方法。 在C ++中,它可以包装成宏,但是如何在Java中优雅地完成它。
答案 0 :(得分:0)
单个方法解决方案需要传入类型:
private Map<Class<?>, Map<String, Object>> instanceMaps;
public <T> T getInstance(String key,
Class<T> instanceType) {
if (instanceMaps == null) {
instanceMaps = new HashMap<>();
instanceMaps.put(ClassA.class, instanceAMap);
instanceMaps.put(ClassB.class, instanceBMap);
instanceMaps.put(ClassC.class, instanceCMap);
}
Map<String, Object> instanceMap = instanceMaps.get(instanceType);
if (instanceMap == null) {
throw new IllegalArgumentException("Unknown type: " + instanceType);
}
Object value = instanceMap.get(key);
if (value == null) {
try {
instanceMap.put(key, value = instanceType.newInstance());
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}
return instanceType.cast(value);
}
instanceAMap,instanceBMap和instanceCMap都必须声明为Map<String, Object>
。无法从单个Map或Collection中检索不同的特定泛型类型。
就个人而言,我不会尝试强制使用单个方法,而是使用重载方法,可以将重构方法重构为单个私有泛型方法。这允许将instanceAMap声明为Map<String, ClassA>
,依旧为instanceBMap和instanceCMap。
private <T> T getInstance(String key,
Map<String, T> instanceMap,
Supplier<T> constructor) {
return instanceMap.computeIfAbsent(key, k -> constructor.get());
}
public ClassA getInstanceA(String key) {
return getInstance(key, instanceAMap, ClassA::new);
}
public ClassB getInstanceB(String key) {
return getInstance(key, instanceBMap, ClassB::new);
}
public ClassC getInstanceC(String key) {
return getInstance(key, instanceCMap, ClassC::new);
}
在Java 8之前的版本中,上述内容可以写成:
private <T> T getInstance(String key,
Map<String, T> instanceMap,
Class<T> instanceType) {
T value = instanceMap.get(key);
if (value == null) {
try {
instanceMap.put(key, value = instanceType.newInstance());
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}
return value;
}
public ClassA getInstanceA(String key) {
return getInstance(key, instanceAMap, ClassA.class);
}
public ClassB getInstanceB(String key) {
return getInstance(key, instanceBMap, ClassB.class);
}
public ClassC getInstanceC(String key) {
return getInstance(key, instanceCMap, ClassC.class);
}
正如@ user902383所说,如果你可以使用一个Map来保存所有的对象和键,那将是很有用的,但显然这需要保证没有两个类将使用相同的键:
public <T> T getInstance(String key,
Class<T> instanceType) {
Object value = instanceMap.get(key);
if (value != null) {
return instanceType.cast(value);
}
try {
T newValue = instanceType.newInstance();
instanceMap.put(key, newValue);
return newValue;
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(e);
}
}