类似“影之分身术”的东西,以“鸣人”为原型,复制1000份出来,群殴之……
在初始化信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,又对性能大大的提高——不用重新初始化对象,而是动态地获得对象运行时的状态。
——摘自《大话设计模式》
提到原型模式,就不得不提深浅克隆。两者都是完成对原型的复制,而区别在于对其引用对象的复制情况:
浅复制:仅仅复制原型,而对其他对象的引用仍指向原有对象,即不复制原型的引用对象。
深复制:把原型和原型的引用对象都复制了一遍。
一、浅复制
以简历复制为例,进行代码演示
①、原型#########################################
/**
* 原型,个人简历,实现Cloneable接口
*/
public class Resume implements Cloneable{
private String name;
private Integer age;
private Character sex;
private WorkExperience work; //工作简历的引用
//初始化姓名
public Resume(String name,WorkExperience work){
this.name = name;
this.work = work;
}
//设置个人信息
public void setPersonalInfo(Character sex,Integer age){
this.sex = sex;
this.age = age;
}
//设计工作经历
public void setWorkExperience(String timeArea,String company){
work.setTimeArea(timeArea);
work.setCompany(company);
}
public void display(){
System.out.println("个人信息:"+name+"\t"+age);
System.out.println("工作经历:"+work.getTimeArea()+"\t"+work.getCompany());
}
@Override
public Object clone(){ //浅克隆,直接调用Object的clone方法
Object ob = null;
try {
ob = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return ob;
}
}
②、原型的引用类#########################################
/**
* 工作简历
*/
public class WorkExperience{
private String timeArea; //时间段
private String company; //所在公司
public String getTimeArea() {
return timeArea;
}
public void setTimeArea(String timeArea) {
this.timeArea = timeArea;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
测试方法:
public class Test {
public static void main(String[] args) throws Exception {
WorkExperience work = new WorkExperience(); //工作简历实例化
Resume a = new Resume("张三",work); //张三的第一份简历
a.setPersonalInfo('男', 23);
a.setWorkExperience("1996-1999", "IBM");
Resume b = (Resume) a.clone(); //张三的第二份简历,工作经验有所改动
b.setWorkExperience("2000-2002", "Microsoft");
System.out.println("第一份简历:");
a.display();
System.out.println("\n第二份简历:");
b.display();
}
}
运行结果为:
Ps:并没有达到预期的效果,把第一份简历的工作经验也修改了
二、深复制
实例以串行化的方式进行深复制,需实现Serializable接口:
①、原型#########################################
/**
* 原型,个人简历,实现Cloneable,Serializable接口
*/
public class Resume implements Cloneable,Serializable{
/**
* ……与浅复制相同部分省略……
*/
@Override
public Object clone(){ //以串行化的方式深度克隆
try {
//将对象写到流里
ByteArrayOutputStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
return oi.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
②、原型的引用类#########################################
/**
* 工作简历,实现Serializable接口
*/
public class WorkExperience implements Serializable{
/**
* ……与浅复制相同部分省略……
*/
}
再次调用测试方法,运行结果为:
Ps:达到预期的效果,单独修改第二份简历工作经验