原型模式
UML类图:
说明:
在Java中不需要ProtoType接口,Java自带克隆接口:Cloneable,只需ConcreteProtoType直接实现Cloneable接口,之后重写 clone()方法即可。
优点:
①隐藏了新对象创建的细节,大大提高了性能,逃避了构造函数的约束。
②在运行期建立和删除原型。
缺点:
①给类配备克隆方法,需要对类的功能进行整体考虑。对于全新的类不难,但对于已有的类不一定容易,如类中含有循环结构。
②必须实现Cloneable接口。
适用范围:创建新对象成本较大,原对象的状态变化不大或占内存不大,就可以用原对象克隆。
客户端:实例化原对象(new),调用此对象的clone()方法,即可得到克隆对象。
//创建原型
Resume a = new Resume();
a.setPersonInfo(“大鸟”,”男”,”29″);
a.setWorkExperience(“1998-2000″,”XX公司”);
// 克隆,并修改(不影响原型)
Resume b = (Resume)a.clone();
b.setPersonInfo(“小菜”,”女”,”20″);
b.setWorkExperience(“2008-2009″,”ZZ公司”);
一句话概括:克隆原对象
Ps:重写clone()方法时,需要注意理解 “浅复制”和“深复制”
类对象中可能包含两种属性:一种是基本类型变量,一种是引用类型变量。
①对于基本类型变量,复制后的新对象的此变量含有与原对象相同的值。
②对于引用类型变量,可分为“浅复制”和“深复制”:
浅复制:复制后的新对象的引用类型变量仍然指向原对象
深复制:复制后的新对象的引用类型变量指向了复制后的新对象,而不是原对象
深复制要深入多少层的引用,要提前考虑,比较复杂,要防止出现循环引用的问题。
附:原对象类,包含重写的clone()方法
public class Resume implements Cloneable {
private String name;
private String age;
private WorkExperience work; //工作经历
public Resume(){
this.work = new WorkExperience();
}
//设置个人信息
public void setPersonInfo(String name,String age){
this.name = name;this.age = age;
}
//填充工作经历
public void setWorkExperience(String workDate, String company){
this.work.setWorkDate(workDate); //工作时间
this.work.setCompany(company); //所在公司
}
//显示
public void display(){
System.out.println(this.name+","+this.sex+","+this.age);
System.out.println(this.work.getWorkDate()+","+this.work.getCompany());
}
//私有构造函数,仅深复制clone()使用,用于克隆“工作经历”数据
private Resume(WorkExperience work){
this.work = work.clone();//当深复制引用时,克隆已有的WorkExperience对象(WorkExperience类中也重写了的clone()方法)
}
//深复制,为新WorkExperience引用类型变量开辟新空间
@Override
public Object clone() {
//完全新创建一个类对象
Resume r = new Resume(this.work); //调用私有构造函数,让“工作经历”克隆完成
r.name = this.name;
r.age = this.age;
return r;
}
//浅复制(新旧引用类型变量的地址会指向同一个)
// @Override
// public Resume clone(){
// Object object = null;
// try {
// object = super.clone();
// } catch (CloneNotSupportedException e) {
// e.printStackTrace();
// }
// return (Resume)object;
// }
}
public class WorkExperience implements Cloneable {
private String workDate;
private String company;
//getter、setter 略
@Override
public WorkExperience clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return (WorkExperience)object;
}
}