说明
记录下学习设计模式-原型模式的写法。
Prototype(原型)
意图:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
结构:
其中:
- Prototype声明一个复制自身的接口。
- ConcretePrototype实现一个复制自身的操作。
- Client让一个原型复制自身从而创建一个新的对象。
适用性:
- 当一个系统应该独立于它的产品创建、构成和表示时。
- 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们,可能比每次用合适的状态手工实例化该类更方便一些。
目录
UML原型模式示例类图
以该UML类图实现原型模式示例。
RealizeType类(浅克隆)
浅克隆:创建一个新对象,新对象的属性和原来完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
Java中的Object类提供了clone()方法来实现浅克隆。
package com.example.deesign_patterns.prototype.demo;
public class RealizeType implements Cloneable{
//idea快捷键生成构造方法:alt+Ins键
public RealizeType() {
System.out.println("具体原型对象创建完成!");
}
@Override
protected RealizeType clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (RealizeType) super.clone();
}
}
测试类
package com.example.deesign_patterns.prototype.demo;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//创建一个原型类对象
RealizeType realizeType=new RealizeType();
//调用RealizeType类中的clone方法进行对象的克隆
RealizeType clone=realizeType.clone();
System.out.println("原型对象和克隆出来的是否是同一个对象?"+(realizeType==clone));//结果为false,说明不是同一个对象
}
}
原型模式案例
类图如下:
奖状类
package com.example.deesign_patterns.prototype.demo2;
//奖状类
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+"同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
protected Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
测试类
package com.example.deesign_patterns.prototype.demo2;
//测试类
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
//1.创建原型对象
Citation citation=new Citation();
//2.克隆奖状对象
Citation citation1=citation.clone();
citation.setName("张三");
citation1.setName("李四");
//3.调用show方法
citation.show();
citation1.show();
}
}
扩展(深克隆)
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
学生类
package com.example.deesign_patterns.prototype.demo3;
import java.io.Serializable;
//学生类必须实现Serializable,不然会抛NotSerializableException异常
public class Student implements Serializable {
//学生的姓名
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
}
奖状类
package com.example.deesign_patterns.prototype.demo3;
import java.io.Serializable;
//奖状类必须实现Serializable,不然会抛NotSerializableException异常
public class Citation implements Cloneable, Serializable {
//学生类
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public void show(){
System.out.println(student.getName()+"同学:在2023学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
protected Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
测试类
使用浅克隆结果如下:
package com.example.deesign_patterns.prototype.demo3;
//测试类
public class CitationTest {
public static void main(String[] args) throws Exception {
//1.创建原型对象
Citation citation=new Citation();
//创建张三学生对象
Student student=new Student();
student.setName("张三");
citation.setStudent(student);
//2.克隆奖状对象
Citation citation1=citation.clone();
citation1.getStudent().setName("李四");
3.调用show方法
citation.show();
citation1.show();
}
}
使用深克隆结果如下:
package com.example.deesign_patterns.prototype.demo3;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//测试类
public class CitationTest {
public static void main(String[] args) throws Exception {
//1.创建原型对象
Citation citation=new Citation();
//创建张三学生对象
Student student=new Student();
student.setName("张三");
citation.setStudent(student);
//使用对象流进行深克隆
//创建对象输出流对象(文件目录随便写,如果没有会自动生成这个文件)
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:/a.txt"));
//写对象
oos.writeObject(citation);
//释放资源
oos.close();
//创建对象输入流对象
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/a.txt"));
//读取对象
Citation citation1= (Citation) ois.readObject();
//释放资源
ois.close();
//2.获取学生对象
citation1.getStudent().setName("李四");
//3.调用show方法
citation.show();
citation1.show();
}
}