模式介绍
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
模式优点
1、性能提高。
2、逃避构造函数的约束。
模式缺点
1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
2、必须实现 Cloneable 接口。
使用场景
1、资源优化、性能和安全要求的场景。
2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
3、通过new产生一个对象,需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
4、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
5、实际项目中,原型模式很少单独出现,一般和工厂模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
系统建模
1、下面解释三种方法Copy对象,第一种为浅拷贝,其余为深拷贝,推荐使用第三种。
系统实现
浅拷贝
/**
* 必须实现Cloneable接口
*/
public class Person implements Cloneable{
private String name;
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
@Override
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
深拷贝(一)
/**
* 本类和内部属性对象,都必须实现Cloneable接口
*/
public class Person implements Cloneable{
private String name;
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
public Person clone() throws CloneNotSupportedException {
Person person = null;
person = (Person) super.clone();
person.child = child.clone();
return person;
}
}
深拷贝(二)
/**
* 推荐使用
*/
public class Person implements Serializable {
private String name;
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
public Person deepCopy(){
Person newPersion = null;
// 创建对象流
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try{
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
newPersion = (Person)ois.readObject();
}catch (Exception e){
e.printStackTrace();
}finally {
try{
bos.close();
oos.close();
bis.close();
ois.close();
}catch (Exception e){
e.printStackTrace();
}
}
return newPersion;
}
}