(七)原型模式

1 概述

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

  • 原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。

  • 一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。

  • 不用重新初始化对象,而是动态地获得对象运行时的状态。

2 浅复制与深复制

  • 浅复制,被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。但我们可能更需要这样的一种需求,把要复制的对象所引用的对象都复制一遍。

  • 深复制,深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

Java中的clone方法:clone方法返回与当前对象的一个副本对象。可以通过操作副本对象而不影响当前对象。使用clone方法需要实现Cloneable接口。并重写Object方法中的clone方法。

  • 代码示例

User.java

public class User implements Cloneable {
    public int age;
    public String name;

    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

Test.java

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user01 = new User(11,"小明");
        User user02 = user01;
        User user03 = (User)user01.clone();
        user01.age = 12;
        user01.name = "小刚";
        System.out.println(user01.toString());
        System.out.println(user02.toString());
        System.out.println(user03.toString());
    }
}

Test.java

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user01 = new User(11,"小明");
        User user02 = user01;
        User user03 = (User)user01.clone();
        user01.age = 12;
        user01.name = "小刚";
        System.out.println(user01.toString());
        System.out.println(user02.toString());
        System.out.println(user03.toString());
    }
}

输出入下

User{age=12, name='小刚'}
User{age=12, name='小刚'}
User{age=11, name='小明'}

Process finished with exit code 0

3 示例

  • 目标:简历的深复制实现
  • 思路:采用原型模型,但是对象成员要采用深复制。

image

工作经历类

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

    public String getWorkDate() {
        return workDate;
    }

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

    public String getCompany() {
        return company;
    }

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

    // “工作经历”类实现克隆方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

简历类

public class Resume implements Cloneable {
    private String name;
    private String sex;
    private int age;
    private WorkExperience work;

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

    // 提供clone方法调用的私有构造函数,以便克隆“工作经历”的数据
    private Resume(WorkExperience work) throws CloneNotSupportedException {
        this.work = (WorkExperience) work.clone();
    }

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

    // 设置工作经历
    public void setWorkExperience(String workDate, String company) {
        this.work.setWorkDate(workDate);
        this.work.setCompany(company);
    }

    public void display() {
        System.out.println(String.format("%s %s %s", name, sex, age));
        System.out.println(String.format("工作经历:%s %s", work.getWorkDate(), work.getCompany()));
    }

    // 调用私有的构造方法,让“工作经历”克隆完成,
    // 然后再给这个“简历”对象的相关字段赋值,
    // 最终返回一个深复制的简历对象
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Resume obj = new Resume(work);
        obj.name = this.name;
        obj.sex = this.sex;
        obj.age = this.age;
        return obj;
    }
}

客户端

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Resume a = new Resume("小明");
        a.setPersonalInfo("男",24);
        a.setWorkExperience("2018-2022","A公司");
        Resume b = (Resume) a.clone();
        b.setWorkExperience("2017-2019", "B公司");
        Resume c = (Resume) a.clone();
        c.setPersonalInfo("男",25);
        c.setWorkExperience("2019-2022","C公司");
        a.display();
        b.display();
        c.display();
    }
}

输出入下

小明 男 24
工作经历:2018-2022 A公司
小明 男 24
工作经历:2017-2019 B公司
小明 男 25
工作经历:2019-2022 C公司
posted @ 2022-11-15 20:29  DaleLee  阅读(30)  评论(0)    收藏  举报