原型模式
作用:用原型实例指定创建对象的种类,并且通过复制(克隆)这些原型创建新的对象。
使用频率:不常用,使用场景非常少。
特点:通过克隆的方式创建对象。
境界:写代码的最高境界就是crtl+c/v,建立自己的技术平台,复用代码,修改代码。
关键点:
抽象原型类:它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至可以是具体实现类。
具体原型类:它实现抽象原型类中声明的方法,在克隆方法中返回自己的一个克隆对象。
客户类:具体原型对象克隆自身从而创建一个全新的对象。
使用场景:构造函数复杂,这样通过new来创建对象需要非常繁琐的数据准备。
例子
简历:将一份简历,复制多次,得到多份简历。
源代码:
package org.yunan.design;
public class prototype {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
Resume a=new Resume("臧宇");
a.setInformation("男", "19", "农大");
Resume b=(Resume)a.clone();
b.setInformation("男", "20", "农大");
Resume c=(Resume)a.clone();
c.setInformation("男", "21", "农大");
a.display();
b.display();
c.display();
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private String workdate;
public Resume(String name) {
super();
this.name = name;
}
public void setInformation(String sex, String age, String workdate) {
this.sex=sex;
this.age=age;
this.workdate=workdate;
}
public void display() {
System.out.println(name+"\t"+sex+"\t"+age+"\t"+workdate);
}
protected Object clone() throws CloneNotSupportedException {
Resume res = (Resume)super.clone();
return res;
}
}
该方法实现的为浅复制
一般步骤:
被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
改进实现深复制
源代码:
package org.yunan.design;
public class prototype2 {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
Resume a=new Resume("臧宇");
a.setInformation("男", "19");
a.setwork("2018","农大" );
Resume b=(Resume)a.clone();
b.setInformation("男", "20");
b.setwork("2019","农大" );
Resume c=(Resume)a.clone();
c.setInformation("男", "21");
c.setwork("2020","农大" );
a.display();
b.display();
c.display();
}
}
class workexperience implements Cloneable{
private String date;
private String company;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public void setCompany(String company) {
this.company = company;
}
public String getCompany() {
return company;
}
protected Object clone() throws CloneNotSupportedException {
return (workexperience)super.clone();
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private workexperience workdate;
public Resume(String name) {
super();
this.name = name;
workdate =new workexperience();
}
public void setInformation(String sex, String age) {
this.sex=sex;
this.age=age;
}
public void setwork(String date,String company) {
workdate.setDate(date);
workdate.setCompany(company);
}
public void display() {
System.out.println(name+"\t"+sex+"\t"+age+"\t"+workdate.getDate()+"\t"+workdate.getCompany());
}
protected Object clone() throws CloneNotSupportedException {
Resume res = (Resume)super.clone();
workexperience work= (workexperience) workdate.clone();
res.workdate=work;
//res.setwork(work.getDate(), work.getCompany());不可取
return res;
}
}
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
以上部分摘取自朱红梅老师2020年5月的课件。