本文参考:
https://www.cnblogs.com/fengyumeng/p/10646487.html
这个博主写的例子也太有意思了,还被博主种草了一本书《码农翻身》,就是以讲故事的形式来讲知识点,很有意思^_^
https://www.cnblogs.com/jenkinschan/p/6399489.html
一、什么是原型模式?
原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。简单理解就是复制对象,得到全新对象,这个全新对象拥有了跟老对象一样的属性值和方法。
二、结构类图
三、应用实例
实例是参照文章开头的博主的实例来写的,是一个写简历的例子,从复杂的实现到应用原型模式来简单的实现例子。
1、写一个简历类
package prototype;
public class Resume {
private String name;
private String position;
private int salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "我的简历" +
"姓名:'" + name + '\'' +
", 求职意向:'" + position + '\'' +
", 期望薪资:" + salary;
}
}
2、开始填写简历信息了
public static void main(String[] args){
//写第一份简历
Resume my1=new Resume();
my1.setName("小仙女");
my1.setPosition("JAVA开发工程师");
my1.setSalary(3000);
System.out.println(my1.toString());
//写第二份简历
Resume my2=new Resume();
my2.setName("小仙女");
my2.setPosition("C++开发工程师");
my2.setSalary(3500);
System.out.println(my2.toString());
//写第二份简历
Resume my3=new Resume();
my3.setName("小仙女");
my3.setPosition("前端开发工程师");
my3.setSalary(3000);
System.out.println(my3.toString());
//...我累了,写不动了
}
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3000
我的简历姓名:'小仙女', 求职意向:'C++开发工程师', 期望薪资:3500
我的简历姓名:'小仙女', 求职意向:'前端开发工程师', 期望薪资:3000
3、这么手写简历太累了,用打印机来循环打印
public static void main(String[] args) {
int num = 5;
while (num > 0){
Resume resume1 = new Resume();
int salary = (int)(3000+Math.random()*(2000-1000+1));
resume1.setName("小仙女");
resume1.setPosition("JAVA开发工程师");
resume1.setSalary(salary);
System.out.println(resume1.toString());
num --;
}
}
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3588
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3789
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3347
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3924
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3521
每次打印都要消耗内存
3、使用Cloneable接口,修改简历类
@Override
protected Resume clone() {
Resume resume = null;
try{
resume = (Resume) super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return resume;
}
4、开始复印
public static void main(String[] args) {
int num = 5;
Resume resume = new Resume();
while (num > 0){
Resume resume1 = resume.clone();
int salary = (int)(3000+Math.random()*(2000-1000+1));
resume1.setName("小仙女");
resume1.setPosition("JAVA开发工程师");
resume1.setSalary(salary);
System.out.println(resume1.toString());
num --;
}
}
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3904
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3797
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3939
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3556
我的简历姓名:'小仙女', 求职意向:'JAVA开发工程师', 期望薪资:3092
和打印机的效果是一样的,但是这里事实上只打印了一次,然后其他的都是拷贝复印出来的。
四、什么时候使用原型模式?
大体上有两种使用场景
-
在需要一个类的大量对象的时候,使用原型模式是最佳选择,因为原型模式是在内存中对这个对象进行拷贝,要比直接new这个对象性能要好很多,在这种情况下,需要的对象越多,原型模式体现出的优点越明显。
-
如果一个对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算,那么可以使用原型模式。
-
当需要一个对象的大量公共信息,少量字段进行个性化设置的时候,也可以使用原型模式拷贝出现有对象的副本进行加工处理。
原型模式中有深度克隆和浅克隆,在浅克隆中需要考虑成员变量对象是否为原生对象(String,Integer等是原生对象),如果是非原生对象还需要层层克隆。而java父类的clone()方法是深度克隆的,我们在例子中也看到了,并没有层层克隆,所以浅克隆就不需过多了解了,java就是那么强大。
其实在java中,自定义的类只要实现了java自带的Cloneable接口就可以被克隆了,并不需要我们自定义一个Clone()方法,本文是为了讨论原型模式的原理才如此做,在现实项目中不用这般复杂。