java中原型模式的两种方法
浅拷贝:
protected Object clone() throws CloneNotSupportedException {
return super.clone();//浅拷贝
}
从Object中继承过来的clone默认实现的是浅拷贝.
深拷贝
方式1:
使用clone方法
protected Object clone() throws CloneNotSupportedException {
Sheep sheep = null;
Sheep sheep= super.clone();//既然默认继承的可以做到浅拷贝,那么就先让其浅拷贝,减少后面手动赋值的代码量.
//然后进行深拷贝;
Sheep sheep1= Sheep(sheep);
sheep1.friend= (One) friend.clone();//让其再次使用引用属性的clone();
return sheep1;
}
此处必须注意的是:对于要拷贝的这个类来说,必须实现cloneable接口;
另外,更更重要的是:将该对象引用的其他对象clone一份,说明被引用的对象也要实现Cloneable接口.但是实现了之后如果这个被引用的对象中还有其他的对象,那么又要进行深拷贝,如此反复循环下去.
第二种方式:
public Object deepClone()
{
ByteArrayInputStream bis=null;
ByteArrayOutputStream bos=null;
ObjectInputStream ois=null;
ObjectOutputStream oos=null;
try{
// 序列化
bos=new ByteArrayOutputStream();
oos=new ObjectOutputStream(bos);
oos.writeObject(this);//当前这个对象以对象流的方式输出
// 反序列化
bis=new ByteArrayInputStream(bos.toByteArray());
ois=new ObjectInputStream(bis);
Object o = ois.readObject();
return ois;
}
catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}finally{
//关闭所有的流;
bos.close();
bis.close();
oos.close();
ois.close();
}
}
public byte[] toByteArray() 创建一个新分配的字节数组。数组的大小和当前输出流的大小,内容是当前输出流的拷贝。
ByteArrayOutputStream:字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。创建字节数组输出流对象有以下几种方式。
下面的构造方法创建一个32字节(默认大小)的缓冲区。
OutputStream bOut = new ByteArrayOutputStream();
另一个构造方法创建一个大小为 a 字节的缓冲区。
OutputStream bOut = new ByteArrayOutputStream(int a)//创建一个大小为a字节的缓冲区;
成功创建字节数组输出流对象后,可以参见以下列表中的方法,对流进行写操作或其他操作。
序号 | 方法描述 |
1 | public void reset() 将此字节数组输出流的 |
2 | public byte[] toByteArray() 创建一个新分配的字节数组。数组的大小和当前输出流的大小,内容是当前输出流的拷贝。 |
3 | public String toString() 将缓冲区的内容转换为字符串,根据平台的默认字符编码将字节转换成字符。 |
4 | public void write(int w) 将指定的字节写入此字节数组输出流。 |
5 | public void write(byte []b, int off, int len) 将指定字节数组中从偏移量 |
6 | public void writeTo(OutputStream outSt) 将此字节数组输出流的全部内容写入到指定的输出流参数中。 |
结论
创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
不用重新初始化对象,而是动态的活的对象运行时的状态
如果原始对象发生变化,变化之后克隆的对象也会发生相应的变化,无序修改代码;
在实现深克隆的时候可能需要比较复杂的代码.
缺点:需要为每一个类配备一个克隆方法,这对全新的类来说,但对已有的类进行改造时,需要修改其源代码,违背了OCP原则(开闭原则);