深入理解原型模式

版权声明:如果转载,请带上来源地址 https://blog.csdn.net/zhan_lang/article/details/88432194

定义:

  1. 原型模式(Prototype Pattern)是指用原型实例指定创建对象的 种类,并且通过拷贝这些原型创建新的对象
  2. 调用者不需要知道任何创建细节,不调用构造函数 属于创建性模式

那么定义有了,它的使用场景又在哪些地方呢?

使用场景:(原型模式是在内存二进制流直接拷贝)

  1. 类初始化消耗资源较多
  2. new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
  3. 构造函数比较复杂
  4. 循环体中生产大量对象时,可读性下降

说了这么多,下边给大家用代码演示一下:
首先呢 我们先创建一个类 ,里面包含年龄,姓名,以及爱好(本想用lombok代替get和set方法 但是我突然用不了)

public  class LocalClone implements Cloneable {

    private String name;

    private int age;
    /**
     * 爱好
     */
    private List<String> like;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<String> getLike() {
        return like;
    }

    public void setLike(List<String> like) {
        this.like = like;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

然后我们来测试一下

public class CloneTest {

    public static void main(String[] args) throws CloneNotSupportedException {
        LocalClone localClone = new LocalClone();
        localClone.setAge(18);
        localClone.setName("张三");
        List<String> strings = new ArrayList<>();
        strings.add("撸代码");
        strings.add("学习");
        localClone.setLike(strings);
        System.out.println("原实例:爱好"+localClone.getLike());

        //修改为使用clone方法
        LocalClone clone = (LocalClone) localClone.clone();
        clone.getLike().add("撩妹");
        clone.setName("李四");

        System.out.println("原实例:爱好"+localClone.getLike() + " 姓名:"+localClone.getName());
        System.out.println("克隆实例:爱好"+clone.getLike()+ " 姓名:"+clone.getName());
    }

}

然后我们来查看一下运行结果:

原实例:爱好[撸代码, 学习]
原实例:爱好[撸代码, 学习, 撩妹] 姓名:张三
克隆实例:爱好[撸代码, 学习, 撩妹] 姓名:李四

是不是很奇怪?为啥我修改一个对象,把另外一个对象的值都修改到了,这种方式就叫浅拷贝,这种方式要慎重使用,特别是在有类继承的时候,一定要慎重 慎重! 要把它和深拷贝分开,不然到时候就把其他对象的值改掉了

下面我们就来介绍一下什么叫浅拷贝和深拷贝

  1. 浅拷贝:只复制对象,对象数组,引用对象都不拷贝 对象修改会相互影响 (例如上面的例子)
  2. 深拷贝:完全拷贝 对象修改互不影响

那深拷贝是怎么实现的呢? 我们就来看一下 这里我们需要修改一下克隆方法,在这里先添加一个
private ArrayList arrayList; 来替换刚才的list,为什么呢?重点来了(因为arrayList有个clone方法)

@Override
    protected Object clone() throws CloneNotSupportedException {
        LocalClone clone = (LocalClone) super.clone();
        this.arrayList  = (ArrayList<String>) this.arrayList.clone();
        return clone;
    }

这是我们修改后的clone方法 重新执行测试类

public class CloneTest {

    public static void main(String[] args) throws CloneNotSupportedException {
        LocalClone localClone = new LocalClone();
        localClone.setAge(18);
        localClone.setName("张三");
        ArrayList<String> strings = new ArrayList<>();
        strings.add("撸代码");
        strings.add("学习");
        localClone.setArrayList(strings);
        System.out.println("原实例:爱好"+localClone.getArrayList());

        //修改为使用clone方法
        LocalClone clone = (LocalClone) localClone.clone();
        clone.getArrayList().add("撩妹");
        clone.setName("李四");

        System.out.println("原实例:爱好"+localClone.getArrayList() + " 姓名:"+localClone.getName());
        System.out.println("克隆实例:爱好"+clone.getArrayList()+ " 姓名:"+clone.getName());
    }

}

查看输入结果:

原实例:爱好[撸代码, 学习]
原实例:爱好[撸代码, 学习] 姓名:张三
克隆实例:爱好[撸代码, 学习, 撩妹] 姓名:李四

这样我们就实现了深拷贝,对于深拷贝我们要做得就是需要手动的去修改克隆方法。(如序列化实现等)

以上就是原型模式,就是这么简单。

注意:
如果定义属性为final的 ,那么就复制不了,因为你都final,我还怎么复制。

拓展:
那么我们长接触的原型模式有哪些呢?例如:BeanUtils.copyProperties(o1,o2); JSON.parseObject(),可以去看看它们是具体实现的

猜你喜欢

转载自blog.csdn.net/zhan_lang/article/details/88432194