• Home
  • Archives
  • 随笔
所有文章 友链 关于我

  • Home
  • Archives
  • 随笔

原型模式learning

发布于: 2021-01-10
更新于: 2023-07-09

原型模式

对已有对象进行 copy 的方式创建新的对象,已达到节省时间的方式,成为原型设计模式(Prototype Design Patern)

拷贝

拷贝上又分为 deep copy 和 shallow copy(浅拷贝)

拿 HashMap.clone()来举例子

Map<String,Object> testMaps=Maps.newHashMap();
TestObject xxx=new TestObject();
testMaps.put(1,xxx);
浅拷贝 深拷贝
只会复制 hashMap 的索引(散列表),而对于 xxx 对象只是 copy 了引用地址 不单散列表,对象也会进行 copy
改变任意一个对象的 value 都会导致另一个 copy 对象发生了改变 深拷贝自然是隔离的,不受影响的,但耗时也随之增长

深拷贝

  • 实现方法
    • 递归拷贝对象,直到对象只包含基本数据类型对象,麻烦复杂
    • 对象序列化,再反序列化为新的对象

实际使用场景中,可以深浅拷贝结合起来,实现 copy-on-write 的思想,对于需要更新的对象进行深拷贝,而无需更新的使用浅拷贝保持一致即可。

BeanUtils.copyProperties()

这个函数分为两个版本,apache 和 springframwork,不建议用 apache 版本,这个做了很多类型转换和检查,执行效果慢,在阿里规约上也是建议禁止项之一。

大致功能就是基于类的字段名的浅拷贝,比如target有name的setter函数,那么就在source处找有没有name的getter函数,若有则直接反射调用设置值writeMethod.invoke(target,value);

    /**
     * Copy the property values of the given source bean into the target bean.
     * <p>Note: The source and target classes do not have to match or even be derived
     * from each other, as long as the properties match. Any bean properties that the
     * source bean exposes but the target bean does not will silently be ignored.
     * <p>This is just a convenience method. For more complex transfer needs,
     * consider using a full BeanWrapper.
     * @param source the source bean
     * @param target the target bean
     * @throws BeansException if the copying failed
     * @see BeanWrapper
     */
    public static void copyProperties(Object source, Object target) throws BeansException {
        copyProperties(source, target, null, (String[]) null);
    }

    /**
     * Copy the property values of the given source bean into the given target bean.
     * <p>Note: The source and target classes do not have to match or even be derived
     * from each other, as long as the properties match. Any bean properties that the
     * source bean exposes but the target bean does not will silently be ignored.
     * @param source the source bean
     * @param target the target bean
     * @param editable the class (or interface) to restrict property setting to
     * @param ignoreProperties array of property names to ignore
     * @throws BeansException if the copying failed
     * @see BeanWrapper
     */
    private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
            @Nullable String... ignoreProperties) throws BeansException {

        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");

        Class<?> actualEditable = target.getClass();
        if (editable != null) {
            if (!editable.isInstance(target)) {
                throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
                        "] not assignable to Editable class [" + editable.getName() + "]");
            }
            actualEditable = editable;
        }
        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
        List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);

        for (PropertyDescriptor targetPd : targetPds) {

            // ==============判断目标类的字段有无写方法先,若无跳过=============
            Method writeMethod = targetPd.getWriteMethod();
            if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
                PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
                if (sourcePd != null) {

                    // ================== 判断源类的字段有无读方法========
                    Method readMethod = sourcePd.getReadMethod();
                    if (readMethod != null &&
                            ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }

                            // ===========反射读============
                            Object value = readMethod.invoke(source);
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }


                            // =========反射写=============
                            // =========由此也可以看出写只是浅显的调用setter函数写下而已,并无做更深层的copy===========
                            // 等同于targetObj.setXXX(sourceObj.getXXX())
                            writeMethod.invoke(target, value);
                        }
                        catch (Throwable ex) {
                            throw new FatalBeanException(
                                    "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
                        }
                    }
                }
            }
        }
    }
原型模式learning
/archives/a3d69698/
作者
tyrantqiao
发布于
2021-01-10
更新于
2023-07-09
许可协议
CC BY-NC-SA 4.0
赏

蟹蟹大佬的打赏,大家一起进步

支付宝
微信

扫一扫,分享到微信

微信分享二维码
恋爱文章学习以及自我剖析
left join与inner join的性能差异到底咋样
© 2024 tyrantqiao 本站总访问量次 本站访客数人次 载入天数...载入时分秒...
  • 所有文章
  • 友链
  • 关于我

tag:

  • 复盘
  • 我
  • 规划
  • java
  • 面试
  • 源码
  • 架构
  • Hadoop
  • HTTP
  • TCP
  • 学习笔记
  • IDEA
  • maven
  • idea
  • Java
  • jdk
  • 面经
  • linux
  • 爱情
  • mysql
  • 性能
  • sql
  • Mysql
  • JAVA
  • 技术
  • Redis
  • MQ
  • Spring
  • 数据库
  • TIDB
  • spring
  • unity
  • chatgpt
  • 经验分享
  • 前端
  • redis
  • vue
  • git
  • shadowsocks
  • hexo
  • blog
  • bug
  • 开发
  • 业务
  • jvm
  • 算法
  • MySQL
  • nginx
  • Linux
  • mq
  • db
  • springCloud
  • ssh
  • python
  • 爬虫
  • test
  • vim
  • 影视剧
  • 中间件
  • 事务
  • 性格
  • 音乐
  • 程序员
  • 随笔
  • mybatis
  • 演讲
  • 域名
  • 猫咪
  • 她
  • github
  • 计划
  • 旅游
  • 软件
  • 心理
  • 情商
  • 幽默
  • 才艺
  • 穿搭
  • 编程
  • 排序
  • 查找
  • 缓存
  • 网络
  • 设计模式
  • c
  • 课程设计
  • centos
  • 数学
  • 本网站主题yilia设计者的主页
如果有问题或者想讨论的可以联系[email protected]或者[email protected]