原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
结构
- 抽象圆形类——规定了具体原型对象必须实现的clone()方法。
- 具体圆形类——实现抽象圆形类的clone()方法。
- 访问类——使用具体圆形类中的clone()方法来复制新的对象。
实现
原型模式的克隆分为浅克隆和深克隆
- 浅克隆——创建一个对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
- 深克隆——创建了一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
Java中的object类就提供了clone()方法来实现浅克隆。
Cloneable接口是上图中的抽象原型类,实现了Cloneable接口的子实现类就是具体的原型类。
我们现在创建一个原型类:
//实现Cloneable接口
public class Realizetype implements Cloneable {
public Realizatype() {
System.out.println("具体的原型对象创建完成!");
}
@Override
Public Realizatype clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (Realizetype)super.clone
}
}
这样,我们就可以创建一个具体原型Realizetype类的实例:
Realizetype realizeType = new Realizetype();
然后调用clone方法就可以进行对象的克隆:
Realizetype clone = realizetype.clone();
这里克隆出来的和原版对象并不是同一个对象,即:
realizetype == clone;//false
🌰举个栗子
我们现在要给三好学生颁发奖状,整张奖状中除名字不同,其余信息均相同,因为我们需要好多份奖状,所以我们就可以使用原型模式复制多个奖状,再一一填上名字即可。
设计类图:
这里的奖状类(Citation)就相当于我们之前的realizatype具体原型类:
public class Citation implements Cloneable {
//填写姓名的地方
private String name;
//省略getter、setter...
//展示奖状内容
public void show() {
System.out.println(name + "同学,本学年被评为三好学生,特发此状!")
}
//重写clone方法
public Citation clone throws CloneNotSupportedException {
return (Citation)super.clone();
}
}
然后我们就可以去测试类中创建奖状啦:
//Test.class
//1.创建一个奖状原型对象
Citation citation = new Citation();
//2.克隆奖状对象
citation citation1 = citation.clone();
//3.写名字
citation.setName("张三");
citation.setName("李四");
当然,这里对象创建方式比较简单,所以会感觉用clone和new一个新对象差别不大,但在对象的创建过程非常复杂时,就可以使用该方式快捷的创建对象。
其次是如果对性能和安全要求比较高的话,可以采用克隆方式,而不是new一个对象。
深克隆
我们可以通过对象操作流来进行深克隆,也就是说先将对象写到文件中,再进行读取,这样读取到的就是一个全新的对象!
//创建对象输出流对象
ObjectOutputStream oos = new ObjectOutputStream(new
//写对象
FileOutputStream(d:/robin/a.txt));
//释放资源
oos.close();
//创建对象输入流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(""));
//读取对象
Citation citation1 = (Citation) ois.readObject();
最终我们获取到的citation1就是深克隆得到的结果!
注:深克隆涉及到的类需要实现Serializable接口,否则会抛NotSerializableException异常。