一、原型模式的作用
在java中我们知道通过new关键字创建的对象是非常繁琐的(类加载判断,内存分配,初始化等),在我们需要大量对象的情况下,原型模式就是我们可以考虑实现的方式。
原型模式 = 克隆模式
概念:以某个对象为原型,克隆出来一个一模一样的对象,该对象的属性和原型对象一模一样,而且对于原型对象没有任何影响。
作用:快速的创建对象,复制对象
二、原型模式的的实现
原型模式的克隆方式有两种:浅克隆 和 深度克隆
原型模式 | 说明 |
---|---|
浅克隆 | 只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址 |
深度克隆 | 深复制把要复制的对象所引用的对象都复制了一遍 |
1、浅克隆
1)特点
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
2)实现方式
<1> Object.clone()
只是拷贝本对象 , 其对象内部的数组、引用对象等都不拷贝 ,还是指向原生对象的内部元素地址
<2> Cloneable,Serializable
被克隆的对象必须Cloneable,Serializable这两个接口
package com.example.test.prototype;
import java.io.Serializable;
import java.util.Date;
public class CloneForShallow implements Cloneable, Serializable {
private String name;
private Date birth;
private int age;
/**
* 实现克隆的方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) throws Exception {
Date date = new Date(666666);
// 原型对象
CloneForShallow prototypeObject = new CloneForShallow();
prototypeObject.setName("小仙");
prototypeObject.setAge(18);
prototypeObject.setBirth(date);
System.out.println("原型对象的属性:" + prototypeObject);
// 克隆对象
CloneForShallow cloneObject = (CloneForShallow) prototypeObject.clone();
System.out.println("克隆对象的属性:" + cloneObject);
// 修改原型对象的属性
date.setTime(12345677);
// 修改克隆对象的属性
cloneObject.setName("小仙~");
System.out.println("原型对象的属性:" + prototypeObject);
System.out.println("克隆对象的属性:" + cloneObject);
}
@Override
public String toString() {
return "CloneForShallow{" +
"name='" + name + '\'' +
", birth=" + birth +
", age=" + age +
'}';
}
}
2、深度克隆
1)特点
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。
那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
换言之,深复制把要复制的对象所引用的对象都复制了一遍。
2)实现方式:2种
方式1:在浅克隆的基础上实现
/**
* 实现克隆的方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
CloneForDeep obj = (CloneForDeep) super.clone();
// 实现深度克隆
obj.birth = (Date) this.birth.clone();
return obj;
}
方式2:通过序列化和反序列化实现
import java.io.*;
import java.util.Date;
public class CloneForDeep implements Cloneable, Serializable {
private String name;
private Date birth;
private int age;
/**
* 实现克隆的方法
*
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) throws Exception {
Date date = new Date(666666);
// 原型对象
CloneForDeep prototypeObject = new CloneForDeep();
prototypeObject.setName("小仙");
prototypeObject.setAge(18);
prototypeObject.setBirth(date);
System.out.println("原型对象的属性:" + prototypeObject);
//使用序列化和反序列化实现深复制
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(prototypeObject);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
// 克隆对象
CloneForDeep cloneObject = (CloneForDeep) ois.readObject();
// 修改原型对象的属性
date.setTime(12345677);
// 修改克隆对象的属性
cloneObject.setName("小仙~");
System.out.println("原型对象的属性:" + prototypeObject);
System.out.println("克隆对象的属性:" + cloneObject);
}
@Override
public String toString() {
return "CloneForShallow{" +
"name='" + name + '\'' +
", birth=" + birth +
", age=" + age +
'}';
}
}