java设计模式 - 原型模式
概念:原型设计模式,就是对对象的内容的拷贝的过程
意义:可能有的对象的实例化过程非常复杂,可以通过原型模式直接进行内存的拷贝进行对象的复制,节省资源
实现:
两种实现方式:
- 实现clonable接口,利用clonable进行对象的拷贝。
对象的浅拷贝于深拷贝的概念:
利用clonable进行对象的拷贝有一个需要注意的地方,clonable在进行对象的拷贝的时候,不会对对象的引用或者数组进行拷贝,对象的引用与数组会直接指向其物理地址空间,不会开辟新的内存去复制引用对象或者数组 – 也叫做对象的浅拷贝,所以通过clonable进行原型模式的编写需要自己进行对象的深拷贝的编写 – 对象的深拷贝。
下面看一下深浅拷贝的测试代码
/**
* 创建一个类,实现clonable的接口,并且类中包含一个ArrayList的属性内容,并重写toString方法
*/
static class Shallow implements Cloneable{
private ArrayList arrayList;
/**
* 构造函数通过传入一个集合 进行实例化
* @param arrayList
*/
Shallow(ArrayList arrayList){
this.arrayList = arrayList;
}
/**
* 直接重写clone方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* 方便观察
* @return
*/
@Override
public String toString() {
return arrayList.toString();
}
}
public static void main(String []args) throws CloneNotSupportedException {
//为实例化一个Shallow对象创建一个集合,集合中添加一个字符串的对象
ArrayList list = new ArrayList();
list.add("a");
//实例化SHallo对象
Shallow shallow = new Shallow(list);
//拷贝出来一个SHallow对象
Shallow shallowCopy = (Shallow) shallow.clone();
//注意,这个 “b” 是在拷贝后添加的内容,如果说shallowCopy与shallow是两个独立的对象,那么会输出什么
list.add("b");
// 输出:[a,b]
System.out.println(shallow);
// 输出:[a,b]
System.out.println(shallowCopy);
// true
System.out.println(shallow.arrayList == shallowCopy.arrayList);
ArrayList arrayListb = new ArrayList();
arrayListb.add("a");
arrayListb.add("b");
//false
System.out.println(arrayListb == list);
}
仔细查看输出内容,都写在注释中了。数组的对象并没有被拷贝,只是将其引用到内存中的地址中了。所以会导致如此输出,当然,如果想实现深拷贝,也很简单
修改Clone方法为以下内容
/**
* 直接重写clone方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Shallow shallow = (Shallow) super.clone();
this.arrayList = (ArrayList) this.arrayList.clone();
return shallow;
}
/*
* 输出结果为
* [a]
* [a, b]
* false
*/
这是数组就为拷贝出来的数组,即进行了深拷贝。
2、
. 利用对象的序列化以及反序列化技术对对象进行复制。
在SHallow类实现了Serializable接口的同时,对Shallow对象转为二进制流的形式,之后再将其二进制流反序列化为一个新的对象,即完成了对象的拷贝,既拷贝了对象的所有的内容包括引用,又没有通过构造方法去实例化对象。
//为实例化一个Shallow对象创建一个集合,集合中添加一个字符串的对象
ArrayList list = new ArrayList();
list.add("a");
//实例化SHallo对象
Shallow shallow = new Shallow(list);
//1、将s1对象序列化为一个数组
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(shallow);
byte mailByte[] = byteArrayOutputStream.toByteArray();
//2、将字节数组中的内容反序列化为一个Sheep对象
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(mailByte);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
list.add("b");
Shallow shallowCopy = (Shallow) objectInputStream.readObject();
// FALSE
System.out.println(shallow.arrayList == shallowCopy.arrayList);
输出为false,证明对象的拷贝是成功的,不是地址的引用的更改,而是真正的物理空间的开辟,创建新的对象。