原型模式属于创建型模式,原型模式最典型的例子就是Java的深拷贝和浅拷贝 (clone方法)。
clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。一般而言,clone()方法满足以下的描述:
(1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。
(2)对任何的对象x,都有:x.clone().getClass() == x.getClass(),换言之,克隆对象与原对象的类型一样。
(3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。
在JAVA语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。JAVA语言的设计师在设计自己的clone()方法时,也应当遵守着三个条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的。
浅拷贝clone()
当进浅拷贝时,clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
同时,复制出来的对象具有与原对象一致的状态。虽然复制出来的对象重新在堆上开辟了内存空间,但是,
对象中各属性确保持相等。对于基本数据类型很好理解,但对于引用数据类型来说,则意味着此引用类型的属性
所指向的对象本身是相同的,并没有重新开辟内存空间存储。换句话说,引用类型的属性所指向的对象并没有复制。
coding:(实现cloneable)重写clone()函数,复制一部电影:
/**
* 导演
* @Author: pk.zhang
* @Date: 2020/2/11 16:57
*/
@Data
public class Director {
private String name;
private int age;
}
/**
* 电影
* @Author: pk.zhang
* @Date: 2020/2/11 16:51
*/
@Data
public class Movie implements Cloneable {
private String movieName;
private int personNum;
private Director director;
@Override
protected Movie clone() throws CloneNotSupportedException {
return (Movie)super.clone();
}
}
Test:
class Test{
public static void main(String[] args) throws CloneNotSupportedException {
Movie movie1 = new Movie();
Director director = new Director();
director.setName("Tom.jackson");
director.setAge(45);
movie1.setMovieName("谍影重重");
movie1.setPersonNum(10);
movie1.setDirector(director);
Movie movie2 = movie1.clone();
System.out.println(movie1 == movie2); // false
System.out.println(movie1.getPersonNum() == movie2.getPersonNum());// true
System.out.println(movie1.getMovieName() == movie2.getMovieName());// true
System.out.println(movie1.getDirector() == movie2.getDirector());// true
}
}
深拷贝deepClone()
Java中的深复制一般是通过对象的序列化和反序列化得以实现。序列化时,需要实现Serializable接口。
深拷贝的特点就是不仅在堆内存上开辟了空间以存储复制出的对象,甚至连对象中的引用类型的属性所指向
的对象也得以复制,重新开辟了堆空间存储。
coding:
需要自己手写deepClone()函数,实现如下:
/**
* 导演
* @Author: pk.zhang
* @Date: 2020/2/11 16:57
*/
@Data
public class Director implements Serializable {
private String name;
private int age;
}
/**
* 电影
* @Author: pk.zhang
* @Date: 2020/2/11 16:51
*/
@Data
public class Movie implements Serializable {
private String movieName;
private int personNum;
private Director director;
public Movie deepClone() throws IOException, ClassNotFoundException {
// 写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 读出二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Movie) ois.readObject();
}
}
TestDeepClone:
class TestDeepClone{
public static void main(String[] args) throws IOException, ClassNotFoundException {
Movie movie1 = new Movie();
Director director = new Director();
director.setName("Tom.jackson");
director.setAge(45);
movie1.setMovieName("谍影重重");
movie1.setPersonNum(10);
movie1.setDirector(director);
Movie movie2 = movie1.deepClone();
System.out.println(movie1 == movie2); // false
System.out.println(movie1.getPersonNum() == movie2.getPersonNum());// true
System.out.println(movie1.getMovieName() == movie2.getMovieName());// false
System.out.println(movie1.getDirector() == movie2.getDirector());// false
}
}
参考连接https://zhuanlan.zhihu.com/p/99381761