一、原型模式
原型模式(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;
}
}
同上一样的客户端类
结果不同
如果文章对你有用,请三连支持一下吧!!!