设计模式

原型模式及使用案例

2022-06-02  本文已影响0人  文景大大

一、模式介绍

原型模式是一种创建型的模式,其核心在于快速复制对象。在Java中创建一个对象的方式有如下几种:

本文的原型模式就是基于第二种方式进行的,该方式是直接基于原始对象在内存中的二进制流直接复制得到拷贝对象,其内容和原始对象完全一致,对比第一种方式,效率更高,无需重复对属性进行赋值操作。原型模式主要适用如下场景:

原型模式通常实现方式如下:

@Data
public class Person implements Cloneable{
    private String name;
    private String country;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
@Slf4j
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person jack = new Person();
        jack.setName("jack");
        jack.setCountry("china");
        // 原始对象为:Person(name=jack, country=china)
        log.info("原始对象为:{}", jack);

        Person mason = (Person)jack.clone();
        mason.setName("mason");
        // 克隆对象为:Person(name=mason, country=china)
        log.info("克隆对象为:{}", mason);
        // 原始对象为:Person(name=jack, country=china)
        log.info("原始对象为:{}", jack);
    }
}

这里可以看到,原始对象jack进行clone后,得到的拷贝对象mason是完全复制的其属性的,mason在修改个别属性后,就完成了自己对象的初始化,就可以进行使用了,无论是复制还是修改,效率都比new提升了不少。

需要注意的是,Cloneable接口提供的clone方法,默认实现的是浅拷贝,只有基本数据类型和基本包装类型是完全复制的,对于引用类型则不是完全拷贝的,具体细节可以参考浅拷贝和深拷贝的常见使用方式 - 简书 (jianshu.com)

二、使用案例

2.1 ArrayList

ArrayList中包含了一个clone方法,基本就类似我们上面写的代码:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    
        /**
     * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
     * elements themselves are not copied.)
     *
     * @return a clone of this <tt>ArrayList</tt> instance
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }
}

根据代码和注释我们也能看到,这是一种浅克隆的原型模式。

2.2 Spring的原型模式

spring默认bean的获取方式是单例的,我们可以通过设置将其改为原型模式,那么每次getBean获取的对象就是完全新的对象。

源码地址尚未找到,后续补充。

三、使用总结

3.1 优点

3.2 缺点

上一篇 下一篇

猜你喜欢

热点阅读