什么是原型模式?
百科定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
通俗的说,就是复制现在的已有对象,来创建新的对象,java对象里的复制粘贴。
实现方式
Object类中提供有本地方法clone,java类只要实现了Cloneable接口,就可以使用clone方法来进行对象的拷贝,使用很简单,下面来看代码:
public class Prototype implements Cloneable {
public int a;
public B b = new B();
// 重写clone方法
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
class B { }
public static void main(String[] args) {
Prototype prototype = new Prototype();
prototype.a=2;
Prototype prototypeClone = (Prototype) prototype.clone();
System.out.println("原对象:" + prototype);
System.out.println("克隆对象:" + prototypeClone);
System.out.println("原对象的属性:" + prototype.a+","+prototype.b);
System.out.println("克隆对象的属性:" + prototype.a+","+prototypeClone.b);
}
}
运行结果:
原对象:com.tangh.test.Prototype@7629b854
克隆对象:com.tangh.test.Prototype@2d04cf67
原对象的属性:2,com.tangh.test.Prototype$B@16cc8a48
克隆对象的属性:2,com.tangh.test.Prototype$B@16cc8a48
从结果可以看出,克隆出的对象也是新的对象,但是对象中的B属性却还是指定同一个地址,说明对象中的对象还未克隆,这就是clone方法的弊端了,只是实现了浅拷贝。
浅拷贝:复制对象中的八大基本数据类型和String类型,其他类型只是复制了对象的引用。
深拷贝:复制对象中的所有属性,除八大基本类型和String类型外的其他类型也全复制为新对象,换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。
有了对深拷贝的认识,改良上述例子中的clone方法,如下:
public class Prototype implements Cloneable {
public int a;
public B b = new B();
// 重写clone方法
public Object clone() {
try {
Prototype p = (Prototype) super.clone();
p.b = (B)b.clone();
return p;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
class B implements Cloneable{
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
public static void main(String[] args) {
Prototype prototype = new Prototype();
prototype.a=2;
Prototype prototypeClone = (Prototype) prototype.clone();
System.out.println("原对象:" + prototype);
System.out.println("克隆对象:" + prototypeClone);
System.out.println("原对象的属性:" + prototype.a+","+prototype.b);
System.out.println("克隆对象的属性:" + prototype.a+","+prototypeClone.b);
}
}
原对象:com.tangh.test.Prototype@2d04cf67
克隆对象:com.tangh.test.Prototype@16cc8a48
原对象的属性:2,com.tangh.test.Prototype$B@4e8a88a9
克隆对象的属性:2,com.tangh.test.Prototype$B@69123787
使Prototype类中的B对象实现cloneable接口,对b也进行clone,这样,对象中的对象属性也就能实现克隆了。
实现原理
clone方法是由java虚拟机直接复制到内存块中,是对二进制字节码的操作处理。
优点
- 由于clone方法是对虚拟机直接复制到内存块执行,所以比new创建对象要快很多。
- 向外部隐藏了创建新实例的复杂性,无需知道创建的细节。
- 可以在运行时动态的获取对象的类型以及状态,从而创建一个对象。
缺点
如果一个对象中属性嵌套很复杂,比如map中有list,list中又是对象,那么要实现深度复制,也不是一件简单的事。