一、概念
当需要创建出多个相同参数的对象时,亦或者这多个对象中,对象类型相同、部分参数不同,那么就可以使用到原型模式。举个例子:在参加校招的时候,大家会准备很多的简历,这些简历很多地方都是相同的,亦或者对于不同的公司,你将会做出部分修改,但是大部分的数据是一致的,接下来就使用这个例子来做演示。
二、代码演示:
(1)首先是创建一个简历类:
//这里继承了一个AbsResume抽象类,是因为里面重写了clone()方法
public class Resume extends AbsResume{
//姓名
private String name;
//性别
private String sex;
//年龄
private String age;
//实习经历
private Work work;
/*
构造行数和set、get方法,tiString都省略了
*/
/**
这是重写了AbsResume抽象类中的clone()方法,用来克隆对象
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
(2)工作经历:
public class Work {
//工作地点
private String location;
//工作时间
private String workTime;
}
(3)客户端:
public class TestResume {
public static void main(String[] args) throws CloneNotSupportedException {
Work work = new Work("北京","2021年9月-2022年5月");
//先创建一个原型对象
Resume zhangsan = new Resume("张三","男","18",work);
//克隆
Resume zhangsan1 = (Resume) zhangsan.clone();
Resume zhangsan2 = (Resume) zhangsan.clone();
System.out.println(zhangsan);
System.out.println(zhangsan1);
System.out.println(zhangsan2);
}
}
(4)输出结果:
可以看到,已经是克隆成功了,那么前面说到,如果有些简历需要做一点小小的修改,那么应该怎么做呢?
public class TestResume {
public static void main(String[] args) throws CloneNotSupportedException {
Work work = new Work("北京","2021年9月-2022年5月");
//先创建一个原型对象
Resume zhangsan = new Resume("张三","男","18",work);
//克隆
Resume zhangsan1 = (Resume) zhangsan.clone();
//年龄设置一下
Resume zhangsan2 = (Resume) zhangsan.clone();
zhangsan2.setAge("20");
System.out.println(zhangsan);
System.out.println(zhangsan1);
System.out.println(zhangsan2);
}
}
输出结果:
这里的age已经做了改变了,但是有一个地方需要注意,那就是如果你直接使用set、get方法修改其中一个对象的Work对象的值,那么其他的都会跟着改变,测试一下:
public class TestResume {
public static void main(String[] args) throws CloneNotSupportedException {
Work work = new Work("北京","2021年9月-2022年5月");
//先创建一个原型对象
Resume zhangsan = new Resume("张三","男","18",work);
//克隆
Resume zhangsan1 = (Resume) zhangsan.clone();
//更改一下zhangsan1的Work对象试试
zhangsan1.getWork().setLocation("上海");
//年龄设置一下
Resume zhangsan2 = (Resume) zhangsan.clone();
zhangsan2.setAge("20");
System.out.println(zhangsan);
System.out.println(zhangsan1);
System.out.println(zhangsan2);
}
}
看看结果:
全部变成了上海,那是咋回事呢?这里涉及到一个知识点深复制和浅复制,可以观察到,如果是String类型,或者说是其他的基本类型,这里直接使用set方法修改是不会影响到其他的,但如果是Work这种对象类型,使用这个set方法就会被更改掉,具体是什么原因造成的呢?
首先明白深复制和浅复制是什么?
浅复制:就是多个变量指向同一个引用地址,真是的对象只有一个,因此一个改变另外一个也就改变了。怎么才可以避免这个问题呢? 可以直接重新创建一个对象,set进去就行了,那么就摆脱了浅复制了。
深复制:就是像zhangsan1、shangsan2这个样的对象,是一对一的,一个变量对应一个引用地址。比如下面这样:
完事儿了, 所以我讲清楚了吗?