(1)概述
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象
(2)结构
- 抽象原型类:规定了具体原型对象必须实现的
clone()
方法 - 具体原型类:实现抽象原型类的
clone()
方法,它是可被复制的对象 - 访问类:使用具体原型类中的
clone()
方法来复制新的对象
接口类图:
(3)实现
原型模式的克隆分为浅克隆和深克隆:
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型,仍指向原有属性所指向的对象的内存地址
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,且不再指向原有对象地址
Java中 Object
类提供了 clone()
方法来实现浅克隆,Cloneable
接口是上面类图中的抽象原型类,而实现了 Cloneable
接口的子实现类就是具体的原型类。
原型类
public class Realizetype implements Cloneable {
public Realizetype() {
System.out.println("具体原型对象创建完成");
}
@Override
public Realizetype clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功");
return (Realizetype) super.clone();
}
}
测试
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象
Realizetype realizetype = new Realizetype();
//调用clone方法进行对象的克隆
Realizetype realizetype1 = realizetype.clone();
//具体原型对象创建完成
//具体原型复制成功
//false
System.out.println(realizetype == realizetype1);
}
}
(4)案例
以学校发放“三好学生”奖状为例
public class Citation implements Cloneable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象
Citation citation = new Citation();
//复制奖状
Citation citation1 = citation.clone();
citation.setName("孙笑川");
citation1.setName("药水哥");
//展示奖状
citation.show();
citation1.show();
}
}
(5)使用场景
- 对象的创建非常复杂
- 性能和安全要求较高
(6)深克隆
将奖状案例中的 name
属性修改为 Student
复杂对象属性
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象
Citation citation = new Citation();
//创建学生
Student student = new Student();
student.setName("孙笑川");
citation.setStudent(student);
//复制奖状
Citation citation1 = citation.clone();
citation1.getStudent().setName("药水哥");
//展示奖状
citation.show();
citation1.show();
//药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!
//药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!
}
}
存在的问题:使用浅克隆时,克隆出来的对象属性中的 student1
和第一次创建的 student
是同一个对象,此时 setName
方法设置的值是同一个
改进:(使用对象流)
public class CitationTest {
public static void main(String[] args) throws Exception {
//创建原型对象
Citation citation = new Citation();
//创建学生
Student student = new Student();
student.setName("孙笑川");
citation.setStudent(student);
//创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(Paths.get("D:/citation.txt")));
//写对象
oos.writeObject(citation);
//释放资源
oos.close();
//创建对象
ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Paths.get("D:/citation.txt")));
Citation citation1 = (Citation) ois.readObject();
ois.close();
citation1.getStudent().setName("药水哥");
citation.show();
citation1.show();
//孙笑川同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!
//药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!
}
}
评论 (0)