原型模式的定义
定义如下:
Specify the kinds of objects to create using a prototypical instance,and create new objects bycopying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)
原型模式通用源码
public class PrototypeClass implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass) super.clone();
} catch (Exception e) {
}
return prototypeClass;
}
}
原型模式的应用
优点
- 性能优良
- 逃避构造函数的约束
使用场景
- 资源优化场景
- 性能和安全要求的场景
- 一个对象多个修改者的场景
原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者
原型模式的注意事项
- 构造函数不会被执行
- 浅拷贝和深拷贝
- clone与final两个冤家(要使用clone方法,类的成员变量上不要增加final关键字。)
什么叫浅拷贝?
public class Thing implements Cloneable {
//定义一个私有变量
private ArrayList<String> arrayList = new ArrayList<>();
public Thing() {
System.out.println("构造函数被执行……");
}
@Override
protected Object clone() throws CloneNotSupportedException {
Thing thing = null;
try {
thing = (Thing) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}
//取得arrayList的值
public ArrayList<String> getArrayList() {
return this.arrayList;
}
//设置arrayList的值
public void setArrayList(String str) {
this.arrayList.add(str);
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Thing thing = new Thing();
thing.setArrayList("张三");
Thing cloneThing = (Thing) thing.clone();
cloneThing.setArrayList("李四");
System.out.println(thing.getArrayList());
}
}
运行结果是什么呢?
[张三,李四]
这是为什么?因为Java做了一个偷懒的拷贝动作,Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。
注意 使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个原始类型或不可变对象。
那什么是深拷贝呢
public class Thing implements Cloneable {
//定义一个私有变量
private ArrayList<String> arrayList = new ArrayList<>();
public Thing() {
System.out.println("构造函数被执行……");
}
@Override
protected Object clone() throws CloneNotSupportedException {
Thing thing = null;
try {
thing = (Thing) super.clone();
thing.arrayList = (ArrayList<String>) this.arrayList.clone();//注意这一行
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}
//取得arrayList的值
public ArrayList<String> getArrayList() {
return this.arrayList;
}
//设置arrayList的值
public void setArrayList(String str) {
this.arrayList.add(str);
}
}
运行结果是
[张三]
该方法就是先了完全的拷贝。两个对象之间没有纠葛,你修改你的,我修改我的。这就叫深拷贝