原型模式可以一个对象再复制另外一个可定制的对象,无需知道如何创建的细节。
原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。
原型模式又可分为浅拷贝和深拷贝,区别在于对引用数据类型的成员变量的拷贝
浅拷贝
在原先Sheep类基础上实现Cloneable接口,重写clone方法
public class Video implements Cloneable {
private String name;
private Date createTime;
//clone是本地方法(native)
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Video() {
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
//客户端克隆
public class ClientCopy {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象 v1
Date date = new Date();
Video v1 = new Video("狂神说java",date);
System.out.println("v1="+v1.getName());
System.out.println("v1="+v1.getCreateTime());
System.out.println("v1=>hash="+v1.hashCode());
//v2克隆v1
Video v2 = (Video)v1.clone();
System.out.println("v2="+v2.getName());
System.out.println("v2="+v2.getCreateTime());
System.out.println("v2=>hash="+v2.hashCode());
}
}
这里的hash值不一样说明它们是两个对象,在内存中的存储位置不同,hash值的计算是通过对象在内存中的逻辑地址进行加工变换的。
import java.util.Date;
//客户端克隆
public class ClientCopy {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象 v1
Date date = new Date();
Video v1 = new Video("狂神说java",date);
System.out.println("v1="+v1.getName());
System.out.println("v1="+v1.getCreateTime());
System.out.println("v1=>hash="+v1.hashCode());
//v2克隆v1
Video v2 = (Video)v1.clone();
System.out.println("v2="+v2.getName());
System.out.println("v2="+v2.getCreateTime());
System.out.println("v2=>hash="+v2.hashCode());
//改变v1的name和date属性:
System.out.println("-------------------------------");
v1.setName("mouse");
date.setTime(2332322);
System.out.println("v1="+v1.getName());
System.out.println("v1="+v1.getCreateTime());
System.out.println("v1=>hash="+v1.hashCode());
System.out.println("v2="+v2.getName());
System.out.println("v2="+v2.getCreateTime());
System.out.println("v2=>hash="+v2.hashCode());
}
}
date的一个复杂属性,如果改变其中一个的date,那么另外一个的date也会改变,如果想让date不改变,我们就需要用到深克隆
深克隆
将对象的属性也克隆一份就行
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Video v = (Video)obj;
//将对象的属性也进行克隆(实现深克隆)
v.createTime = (Date)this.createTime.clone();
return obj;
}
总结
1、浅拷贝和深拷贝区别
拷贝基本类型之前互不影响,引用类型其中一个对象改变了地址,就会影响另一个对象;深拷贝改变新对象不会影响原对象,他们之前互不影响,但代码量大。
2、优点
- 性能优良,Java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升了许多。
- 浅拷贝我们复制一个类的时候,改变一个类另一个类的引用类型也改变,在一些时候可以减少很多重复的代码
3、缺点:
- 克隆方法位于类的内部,当对已有类进行该操的时候,需要修改代码,违反了开闭原则。