概念:
原形模式:
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
演示:
package com.dairuijie.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个
对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对。在 Java 中,复制对象是通过 clone()实现的
实现深复制需要实现Serializable 可以序列化 不然没法序列化对象去进行流的输入输出
* @author DRJYY
*
*/
public class Prototype implements Cloneable,Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer age;
private String name;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 浅复制
*/
@Override
protected Object clone() throws CloneNotSupportedException {
/* Prototype prot = (Prototype) super.clone();
return prot;*/
return super.clone();
}
/**
* 深复制
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepClone() throws IOException, ClassNotFoundException{
/**
* 写入当前对象的二进制流
*/
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject( this );
/**
* 写出当前对象二进制流
*/
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois;
ois = new ObjectInputStream(bis);
return ois.readObject();
}
public Prototype(Integer age, String name) {
this.age = age;
this.name = name;
}
}
package com.dairuijie.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 学生实体类 除了基本数据类型 同时包括Prototype 引用 方便我们测试结果
* @author DRJYY
*
*/
public class Student implements Cloneable,Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer age;
private String name;
private Prototype prototype;
public Prototype getPrototype() {
return prototype;
}
public void setPrototype(Prototype prototype) {
this.prototype = prototype;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Student(Integer age, String name, Prototype prototype) {
this.age = age;
this.name = name;
this.prototype = prototype;
}
public Object deepClone() throws IOException, ClassNotFoundException{
/**
* 写入当前对象的二进制流
*/
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject( this );
/**
* 写出当前对象二进制流
*/
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois;
ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
package com.dairuijie.prototype;
import java.io.IOException;
/**
*
* @author DRJYY
*
*/
public class ShallowTest {
public static void main(String[] args) throws ClassNotFoundException, IOException {
Prototype p = new Prototype(12, "dai");
Student student = new Student(13, "dai", p);
Student stu = (Student) student.deepClone();
stu.getPrototype().setAge(123);
stu.setAge(11);
System.out.println("原始的student的年龄----"+student.getAge());
System.out.println("克隆对象----"+stu.getAge());
System.out.println("克隆对象中的p 引用---"+stu.getPrototype().getAge());
System.err.println("p的对象原始----"+p.getAge());
}
}
package com.dairuijie.prototype;
public class DeepTest {
public static void main(String[] args) throws CloneNotSupportedException {
Prototype p = new Prototype(12, "dai");
Student student = new Student(13, "dai", p);
Student stu = (Student) student.clone();
stu.getPrototype().setAge(123);
stu.setAge(11);
System.out.println("原始的student的年龄----"+student.getAge());
System.out.println("克隆对象----"+stu.getAge());
System.out.println("克隆对象中的p 引用---"+stu.getPrototype().getAge());
System.err.println("p的对象原始----"+p.getAge());
}
}
图一 : 图二:
如图一就是浅复制结果 发现p 的对象年龄没有变化,图二深复制中p 的对象年龄却被身体stu.getPrototype().setAge(123) 改变了。说明深复制将引用对象都复制过来了。也就是对引用类型的成员变量也进行引用对象的复制。