系列文章目录
前言
原型设计模式简单来说就是克隆。原型表明了有一个样板实例,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
使用方法
- 首先实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
- 然后重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此Prototype类需要将clone方法的作用域修改为public类型。
原型模式分为浅复制和深复制
- (浅复制)只是拷贝了基本类型的数据,而引用类型数据,只是拷贝了一份引用地址。
- (深复制)在计算机中开辟了一块新的内存地址用于存放复制的对象
原型模式的代码实现
public class PrototypeDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep parent = new Sheep("萝卜",20,null); //设置羊的母亲
Sheep sheep = new Sheep("青菜",10,parent);
Sheep cloneObj = sheep.clone();
System.out.println(sheep==cloneObj);
System.out.println(sheep);
System.out.println(cloneObj);
/**
* false
* 990368553/name:青菜/age:10/parent:1096979270
* 793589513/name:青菜/age:10/parent:1096979270
*/
}
}
class Sheep implements Cloneable{
private String name;
private Integer age;
private Sheep parent;
Sheep(String name,int age,Sheep parent){
this.name = name;
this.age = age;
this.parent = parent;
}
@Override
protected Sheep clone() throws CloneNotSupportedException {
return (Sheep) super.clone();
}
@Override
public String toString() {
return this.hashCode()+"/"+"name:"+this.name+"/"+"age:"+this.age+"/"+"parent:"+this.parent.hashCode();
}
}
可见虽然sheep和cloneObj不是同一个对象,但是parent只是复制了引用地址,parent的hashcode相同,指向的还是同一个对象,此时是浅复制,如果要实现深拷贝,再将sheep.parent 进行复制,这样就实现了递归复制。
public class PrototypeDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep parent = new Sheep("萝卜",20,null); //设置羊的母亲
Sheep sheep = new Sheep("青菜",10,parent);
Sheep cloneObj = sheep.clone();
System.out.println(sheep==cloneObj);
System.out.println(sheep);
System.out.println(cloneObj);
/**
* false
* 990368553/name:青菜/age:10/parent:1096979270
* 793589513/name:青菜/age:10/parent:1313922862
*/
}
}
class Sheep implements Cloneable{
private String name;
private Integer age;
private Sheep parent;
Sheep(String name,int age,Sheep parent){
this.name = name;
this.age = age;
this.parent = parent;
}
@Override
protected Sheep clone() throws CloneNotSupportedException {
Sheep sheep = (Sheep) super.clone();
if(sheep.parent!=null){
sheep.parent = sheep.parent.clone();
}
return sheep;
}
@Override
public String toString() {
return this.hashCode()+"/"+"name:"+this.name+"/"+"age:"+this.age+"/"+"parent:"+this.parent.hashCode();
}
}
可见sheep的parent 和cloneObj的parent 哈希码已经不同了,parent也进行了复制,这就是深复制。
原型模式的优点
- 可以不耦合具体类的情况下克隆对象
- 避免重复的初始化代码
- 更方便的构建复杂对象
原型模式的使用场景
- 资源优化场景。
- 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
- 性能和安全要求的场景。
- 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
- 一个对象多个修改者的场景。
- 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
原型模式在JDK中的使用
在ArrayList中的使用
通过注释可以了解到ArrayList实现的clone方法也是浅复制