原型模式,深浅拷贝

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_28196435/article/details/86760485

原型模式

原型模式是一个比较简单的创建模式,在java中当需要创建大量对象的时候,为了提升效率和性能,我们可以使用原型模式
原型模式一般和工厂模式配合使用,用来创建对象
下面介绍java的原型模式实现过程


Java的Object类中具有clone方法,这表示任何对象都可以实现克隆,如下所示

package com.natsuki;

import java.util.Date;

/**
 * @author natsuki
 * created at 2018-11-29
 */
public class WeeklyLog implements Cloneable {
    private String name;
    private String date;
    private String content;

    private Date birthday;
    private Attachment attachment;

    public String getName() {
        return name;
    }

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

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Attachment getAttachment() {
        return attachment;
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

    @Override
    public WeeklyLog clone(){
        WeeklyLog weeklyLog = null;
        try {
            weeklyLog = (WeeklyLog) super.clone();
            weeklyLog.attachment = attachment.clone();
            weeklyLog.birthday = (Date) birthday.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return weeklyLog;
    }

    @Override
    public String toString() {
        return "WeeklyLog{" +
                "name='" + name + '\'' +
                ", date='" + date + '\'' +
                ", content='" + content + '\'' +
                ", birthday=" + birthday +
                ", attachment=" + attachment +
                '}';
    }
}

package com.natsuki;

import java.text.MessageFormat;

/**
 * @author natsuki
 * created at 2018-11-29
 */
public class Attachment implements Cloneable{
    private String name;

    public String getName() {
        return name;
    }

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

    public void download(){
        System.out.println(MessageFormat.format("下载附件,文件名为:{0}",this.name));
    }


    @Override
    public Attachment clone() {
        Attachment attachment = null;
        try {
            attachment = (Attachment) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return attachment;
    }
}

这里需要注意两点,首先需要继承Cloneable标志接口,然后重写clone方法,注意这里由于Date类型的属性和Attachment类型的属性都是对象属性,在默认的clone方法中只能进行浅拷贝,即拷贝的是对象地址,所以为了进行深拷贝需要重写编写clone方法。将对象类型进行手动拷贝。
当然我们还可以使用序列化和反序列化的方式实现深拷贝


js中也有深浅拷贝的概念,比如Object.assign默认的就是浅拷贝,另外我们还可以通过展开运算符 ... 来实现浅拷贝。

let a = {
  age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
let a = {
  age: 1,
  jobs: {
    first: 'FE'
  }
}
let b = { ...a }
a.jobs.first = 'native'
console.log(b.jobs.first) // native

第二个例子就说明了浅拷贝,实际上a和b中的jobs还是同一个对象。
大部分浅拷贝是足够应付业务的,但是如果要实现深拷贝的话,通常可以使用JSON.parse(JSON.stringify(object))来解决

let a = {
  age: 1,
  jobs: {
    first: 'FE'
  }
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是这个方法有个明显的坑,就是不能序列化函数。。在带有函数的对象中就无能为力了。

let a = {
  age: undefined,
  sex: Symbol('male'),
  jobs: function() {},
  name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}

包括Symbol和undefined类型,也不能序列化
如果序列化不能满足需求的话,这里推荐使用lodash的工具函数进行深拷贝

猜你喜欢

转载自blog.csdn.net/baidu_28196435/article/details/86760485