java 怎么动态实现多例

发布于 2022-09-11 19:01:34 字数 586 浏览 21 评论 0

Java动态生成一个类的多个实例,这些实列对象只生成一次,多次使用

一个类控制为只产生一个类实例,则是单例,如果,现在想生成该类的多个实例,每个实例只实例化一次,下次要使用判断是否有对应一个实例,有则直接使用,没有则实例化一个新的。

或者如何封装下面一段代码,写成类

VideoProcessorJNI videoptr = new VideoProcessorJNI();
VideoProcessorJNI videoptr2 = new VideoProcessorJNI();
videoptr.VideoProcessInit("101");//构造函数的参数是101,生成101实例
videoptr2.VideoProcessInit("102");//构造函数的参数是102,生成102实例
while(true){
    videoptr.VideoProcessGetimg("/home/jni/5.jpg");
    videoptr2.VideoProcessGetimg("/home/jni/6.jpg");
}

101,102这些构造函数中的参数是动态获取的,使用spring boot框架

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

虚拟世界 2022-09-18 19:01:34

用一个HashMap保存不就好了

站稳脚跟 2022-09-18 19:01:34

单例构造函数添加一个参数(懒汉式),构造函数中传入参数

private String streamUrl; 
/**
*构造函数私有
**/
private VideoProcessorJNI(String arg) {
    this.streamUrl = streamUrl;
}
private static VideoProcessorJNI videoProcessorJNI;
public static VideoProcessorJNI getVideoProcessorJNI(String streamUrl) {
    if(videoProcessorJNI==null) {
        videoProcessorJNI = new VideoProcessorJNI(streamUrl);
    }
    return videoProcessorJNI;
}

目前这样实现至少感觉是实现了问题描述的现象,有大神方便指出下这个单例的机制吗?

街道布景 2022-09-18 19:01:34

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

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

1. 提供创建实例的参数,这是输入
2. 根据实例的参数类型,找到匹配的构造函数
3. 先从缓存中,根据当前参数值+匹配的构造函数找当前是否已经存在了实例,若存在则直接返回实例
4. 若不存在,则用当前参数值+匹配的构造函数创建一个新实例,把相关数据放入缓存中,再返回新实例,这是输出

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

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

public static final InstanceFactory<VideoProcessorJNI> 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<String, Constructor> constructorMap;
private Map<String, Map<Constructor, T>> 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;
    }

constructorMapkey其实就是当前参数类型的全名用'-'拼起来的

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<T> 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<T>的完整代码

public class InstanceFactory<T> {

    private Map<String, Constructor> constructorMap;
    private Map<String, Map<Constructor, T>> 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<T> 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<T> constructor, T t) {
        Map<Constructor, T> 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<VideoProcessorJNI> 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);
    }
}

运行结果

clipboard.png

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文