java 多例_java 怎么动态实现多例

  • Post author:
  • Post category:java


题主,你好

看到你这个问题,我最开始联想到了Spring的控制反转,这很相似,就是实例有一个统一管理的地方,只是题主要求是根据参数不同来区分是否要创建新的实例,也就是说,实例创建决定于参数,那我们再更引申一点,不同的参数,若是不止不同于值,更不同在个数和类型上的话,那此时,实例创建决定于与参数和构造方法

所以下面的代码会把两个因素都考虑进去,结合我自己理解题主的意思,我总结了整个问题需要进入怎样的步骤最终创建一个实例出来,其实就是怎么写这个实例工厂

1. 提供创建实例的参数,这是输入

2. 根据实例的参数类型,找到匹配的构造函数

3. 先从缓存中,根据当前参数值+匹配的构造函数找当前是否已经存在了实例,若存在则直接返回实例

4. 若不存在,则用当前参数值+匹配的构造函数创建一个新实例,把相关数据放入缓存中,再返回新实例,这是输出

那现在我新增一个实例工厂类InstanceFactory,这个类中保存了某一个类的所有构造函数,也保存了该类所有的参数值+构造函数+实例的信息(这里有一个泛型,是方便最终你拿到的实例就是所要的实例,不用强转)

所以我要初始化某一个工厂时,我采用了这个init方法进行初始化,由于InstanceFactory初始化中对于参数值+构造函数是一个固定的数据,所以把这个工厂写成了静态变量放在了所需要创建实例的类VideoProcessorJNI中

public static final InstanceFactory instanceFactory = InstanceFactory.init(VideoProcessorJNI.class);

当然最终我会采取一个简单的public T get(Object … params)方法,来获取实例值,由于参数可变,所以get方法的参数也是可变的

VideoProcessorJNI videoProcessorJNI = VideoProcessorJNI.instanceFactory.get(“123”);

VideoProcessorJNI videoProcessorJNI1 = VideoProcessorJNI.instanceFactory.get(“xxxx”);

VideoProcessorJNI videoProcessorJNI2 = VideoProcessorJNI.instanceFactory.get(“123”);

现在我们就可以来填补刚才那几个方法了,首先是init方法,由于我们要保存参数类型+构造函数的关系,以及参数值+参数值+构造函数+实例的关系,所以会有两个map来存储关系

private Map constructorMap;

private Map> instanceMap = new HashMap<>();

所以init方法就简单了,我们只需要初始化constructorMap即可,并最终创建这个工厂返回

public static InstanceFactory init(Class targetClass){

Constructor[] declaredConstructors = targetClass.getDeclaredConstructors();

InstanceFactory factory = new InstanceFactory();

factory.constructorMap = Arrays.stream(declaredConstructors).collect(Collectors.toMap(InstanceFactory::toConstructorMapKey, Function.identity()));

return factory;

}

constructorMap的key其实就是当前参数类型的全名用’-‘拼起来的

private static String toConstructorMapKey(Constructor constructor){

Class[] parameterTypes = constructor.getParameterTypes();

String key = toConstructorMapKey(parameterTypes);

return key;

}

private static String toConstructorMapKey(Class … paramClassArray){

if (paramClassArray == null || paramClassArray.length == 0) return “”;

String key = Arrays.stream(paramClassArray).map(Class::getName).collect(Collectors.joining(“-“));

return key;

}

初始化了constructorMap,我们现在就可以来做get方法的处理了

public T get(Object … params){

String key = toConstructorMapKey(params);

Constructor constructor = constructorMap.get(key);

String instanceKey = toInstanceMapKey(params);

if (instanceMap.containsKey(instanceKey) && instanceMap.get(instanceKey).containsKey(constructor)){

return instanceMap.get(instanceKey).get(constructor);

}

try {

T t = constructor.newInstance(params);

this.putToInstanceMap(instanceKey, constructor, t);

return t;

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return null;

}

其实方法看起来也挺简单的,下面是InstanceFactory的完整代码

public class InstanceFactory {

private Map constructorMap;

private Map> instanceMap = new HashMap<>();

private InstanceFactory() {

}

public static InstanceFactory init(Class targetClass){

Constructor[] declaredConstructors = targetClass.getDeclaredConstructors();

InstanceFactory factory = new InstanceFactory();

factory.constructorMap = Arrays.stream(declaredConstructors).collect(Collectors.toMap(InstanceFactory::toConstructorMapKey, Function.identity()));

return factory;

}

public T get(Object … params){

String key = toConstructorMapKey(params);

Constructor constructor = constructorMap.get(key);

String instanceKey = toInstanceMapKey(params);

if (instanceMap.containsKey(instanceKey) && instanceMap.get(instanceKey).containsKey(constructor)){

return instanceMap.get(instanceKey).get(constructor);

}

try {

T t = constructor.newInstance(params);

this.putToInstanceMap(instanceKey, constructor, t);

return t;

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return null;

}

private void putToInstanceMap(String key, Constructor constructor, T t) {

Map constructorTMap = this.instanceMap.getOrDefault(key, new HashMap());

constructorTMap.put(constructor, t);

this.instanceMap.put(key, constructorTMap);

}

private String toInstanceMapKey(Object … paramArray) {

if (paramArray == null || paramArray.length == 0) return “”;

String key = Arrays.stream(paramArray).map(Object::toString).collect(Collectors.joining(“-“));

return key;

}

private static String toConstructorMapKey(Constructor constructor){

Class[] parameterTypes = constructor.getParameterTypes();

String key = toConstructorMapKey(parameterTypes);

return key;

}

private static String toConstructorMapKey(Class … paramClassArray){

if (paramClassArray == null || paramClassArray.length == 0) return “”;

String key = Arrays.stream(paramClassArray).map(Class::getName).collect(Collectors.joining(“-“));

return key;

}

private static String toConstructorMapKey(Object … paramArray){

if (paramArray == null || paramArray.length == 0) return “”;

Class[] paramClassArray = Arrays.stream(paramArray).map(Object::getClass).toArray(Class[]::new);

return toConstructorMapKey(paramClassArray);

}

}

下面可以来做一下测试

public class VideoProcessorJNI {

public static final InstanceFactory instanceFactory = InstanceFactory.init(VideoProcessorJNI.class);

private String param;

private Integer param1;

public VideoProcessorJNI(String param, Integer param1) {

this.param = param;

this.param1 = param1;

}

public VideoProcessorJNI(String param) {

this.param = param;

}

public static void main(String[] args) {

VideoProcessorJNI videoProcessorJNI = VideoProcessorJNI.instanceFactory.get(“123”);

VideoProcessorJNI videoProcessorJNI1 = VideoProcessorJNI.instanceFactory.get(“xxxx”);

VideoProcessorJNI videoProcessorJNI2 = VideoProcessorJNI.instanceFactory.get(“123”);

VideoProcessorJNI videoProcessorJNI3 = VideoProcessorJNI.instanceFactory.get(“123”, 1);

VideoProcessorJNI videoProcessorJNI4 = VideoProcessorJNI.instanceFactory.get(“123”, 2);

VideoProcessorJNI videoProcessorJNI5 = VideoProcessorJNI.instanceFactory.get(“123”, 1);

System.out.println(videoProcessorJNI);

System.out.println(videoProcessorJNI1);

System.out.println(videoProcessorJNI2);

System.out.println(videoProcessorJNI3);

System.out.println(videoProcessorJNI4);

System.out.println(videoProcessorJNI5);

}

}

运行结果

2a1b5eae7f76eee3eb93f474f56841f8.png

以上就是我个人的看法,仅供参考



版权声明:本文为weixin_34637138原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。