【大话设计模式】模式四:原型模式与浅谈Cloneable浅复制、深复制

 一、原型模式

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式(Prototype)结构图 :

Prototype原型类,声明一个克隆自身的接口。

ConcretePrototype具体原型类,实现一个克隆自身的接口。

【代码实现】:

Prototype类

public abstract class Prototype {
    private String id;

    public Prototype(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public abstract Prototype Clone() throws CloneNotSupportedException;
}

 ConcretePrototype1类

public class ConcretePrototype1 extends Prototype implements Cloneable {
    public ConcretePrototype1(String id) {
        super(id);
    }
    //克隆的对象必须实现Cloneable这个接口,而且需要重写clone方法
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public Prototype Clone() throws CloneNotSupportedException {
        return (Prototype)this.clone();
    }
}

Client类

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        ConcretePrototype1 p1=new ConcretePrototype1("001");
        ConcretePrototype1 p2=(ConcretePrototype1)p1.clone();
        System.out.println(p2.getId());
    }
}

二、浅复制与深复制

        Cloneable接口的clone()方法是这样的,如果字段是值类型的,则该字段执行逐位复制;如果是引用类型的,则复制引用但是不复制引用的对象,因此,原始对象及其副本引用同一个对象。

结合原型模式应用场景——PPT简历复制: 

UML图

浅复制实现: 

 具体原型类:

public class Resume implements Cloneable {
    /**
     * 原型模式,浅复制
     */
    private String name;
    private String sex;
    private String age;
    private WorkExperience work;

    public Resume(String name) {
        this.name = name;
        work = new WorkExperience();
    }

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

    //设置个人信息
    public void SetPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    //设置工作信息
    public void SetWorkExperience(String workDate, String company) {
        work.setWorkDate(workDate);
        work.setCompany(company);
    }

    //显示简历信息
    public void display() {
        System.out.println(name + " " + age + " " + sex);
        System.out.println(work.getWorkData() + " " + work.getCompany());
    }

    //重写clone()方法
    public Resume clone() throws CloneNotSupportedException {
        return (Resume) super.clone();
    }
}

简历resume里面包含工作经历workExperience

public class WorkExperience implements Cloneable {
    private String workDate;
    private String company;

    public String getWorkData() {
        return workDate;
    }

    public String getCompany() {
        return company;
    }

    public void setWorkDate(String workData) {
        this.workDate = workData;
    }

    public void setCompany(String company) {
        this.company = company;
    }

}

Client类

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Resume r1=new Resume("小李");
        r1.SetPersonalInfo("男","23");
        r1.SetWorkExperience("2017-2020","字节跳动");

        Resume r2=r1.clone();
        r2.SetPersonalInfo("女","23");
        r2.SetWorkExperience("2017-2021","字节跳动");

        r1.display();
        r2.display();
    }
}

运行结果

        可以看到两个引用都是最后一次修改的结果,因此指向了两个引用都同一个对象。

        浅复制,被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象但我们可能更需要这样的一种需求,把要复制的对象所引用的对象都复制一遍,比如刚才的例子,我们希望是a、b、c三个引用的对象都是不同的,复制时就一变二,二变三,此时,我们就叫这种方式为,深复制,深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

 深复制实现:

public class WorkExperience implements Cloneable {
    private String workDate;
    private String company;

    public String getWorkData() {
        return workDate;
    }

    public String getCompany() {
        return company;
    }

    public void setWorkDate(String workData) {
        this.workDate = workData;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public WorkExperience clone() throws CloneNotSupportedException {
        return (WorkExperience) super.clone();
    }
}
public class Resume implements Cloneable {
    /**
     * 原型模式,深复制
     */
    private String name;
    private String sex;
    private String age;
    private WorkExperience work;

    public Resume(String name) {
        this.name = name;
        work = new WorkExperience();
    }

    private Resume(WorkExperience work) throws CloneNotSupportedException {
        this.work=(WorkExperience) work.clone();
    }

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

    //设置个人信息
    public void SetPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    //设置工作信息
    public void SetWorkExperience(String workDate, String company) {
        work.setWorkDate(workDate);
        work.setCompany(company);
    }

    //显示简历信息
    public void display() {
        System.out.println(name + " " + age + " " + sex);
        System.out.println(work.getWorkData() + " " + work.getCompany());
    }

    //重写clone()方法
    public Resume clone() throws CloneNotSupportedException {
        Resume resume=new Resume(this.work);
        resume.setName(this.name);
        resume.SetPersonalInfo(this.sex,this.age);
        return resume;
    }
}

同上一样的客户端类

结果不同


如果文章对你有用,请三连支持一下吧!!!

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值