3.2 原型模式(Prototype)
原型模式(Prototype),在制造业中通常是指大批量生产开始之前研发出的概念模型,并基于各种参数指标对其进行检验,如果达到了质量要求,即可参照这个原型进行批量生产。原型模式达到以原型实例创建副本实例的目的即可,并不需要知道其原始类,也就是说,原型模式可以用对象创建对象,而不是用类创建对象,以此达到效率的提升。
结构
原型模式包含如下角色:
- 抽象原型类:规定了具体原型对象必须实现的clone()方法。
- 具体原型类:实现抽象原型类的clone()方法,是可被复制的对象。
- 访问类:使用具体原型类中的clone()方法来复制新的对象。
模式的实现
原型模式的克隆分为如下两类:
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍然指向原有属性的对象的内存地址;
- 深克隆:创建一个新对象,新对象中的非基本类型属性的对象也会被克隆,不再指向原有对象地址。
Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。
//具体原型类
class Realizetype implements Cloneable {
Realizetype() {
System.out.println("具体原型创建成功!");
}
public Object clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (Realizetype) super.clone();
}
}
//原型模式的测试类
public class PrototypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
Realizetype obj1 = new Realizetype();
Realizetype obj2 = (Realizetype) obj1.clone();
System.out.println("obj1==obj2?" + (obj1 == obj2));
}
}
【案例】奖状克隆
使用原型模式生成“三好学生”奖状——奖状的获奖人姓名不同,其余相同。
浅克隆实现代码:
//奖状类
public class Citation implements Cloneable {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return (this.name);
}
public void show() {
System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
//测试访问类
public class CitationTest {
public static void main(String[] args) throws CloneNotSupportedException {
Citation c1 = new Citation();
c1.setName("张三");
//复制奖状
Citation c2 = c1.clone();
//将奖状的名字修改李四
c2.setName("李四");
c1.show();
c2.show();
}
}
深克隆实现:
//奖状类
public class Citation implements Cloneable {
private Student stu;
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
void show() {
System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
//重写clone()方法,并实现Student类的clone()方法
@Override
public Citation clone() throws CloneNotSupportedException {
Citation citation = (Citation)super.clone();
Student student = citation.getStu().clone();
citation.setStu(student);
return citation;
}
}
//学生类
public class Student implements Cloneable{
private String name;
private String address;
public Student(String name, String address) {
this.name = name;
this.address = address;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
原型模式的应用场景
原型模式适用于如下场景:
- 对象之间相同或类似,即只是个别几个属性不同;
- 创建对象的成本较大,例如初始化时间长,占用CPU时间太多,或者专用网络资源太多等,需要优化资源。
- 创建一个对象需要繁琐的的数据准备或访问权限等,需要提高安全性。
- 系统中大量使用该类对象,且各个吊用这都需要给它的属性重新赋值。
在 Spring 中,原型模式应用的非常广泛,例如 scope=‘prototype’、JSON.parseObject() 等都是原型模式的具体应用。