原型模式
Prototypye
简介
原型模式
类似复制粘贴功能
创建一个实例,用这个实例去拷贝创建新实例(直接从内存中拷贝)
角色
- 抽象原型(Prototype)
- 核心:需要实现Cloneable接口,重写clone方法
- 说明这个类能够被克隆复制的功能
- 具体原型(Concrete Prototype)
- 实现抽象原型类
- 客户端(Cline)
- 提出创建对象请求(用户使用复制粘贴)
大话设计模式中的图片
分类
浅拷贝(浅克隆)
基本类型拷贝是值传递,引用类型拷贝的是同一个内存地址
改变原对象的引用类型字段时,副本对象的该字段也会被修改
注意: 如果改变的是String类型,虽然它是引用类型,但String不可变,它实际上并不是在原有的内存地址上改动,而是给原对象String字段换了一块内存地址,所以副本对象该字段不会变
浅克隆代码
public class Prototype implements Cloneable {
private String fileName;
private Integer fileId;
private Date time;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//核心
}
public Prototype(String fileName, Integer fileId, Date time) {
this.fileName = fileName;
this.fileId = fileId;
this.time = time;
}
// get/set方法
}
public class ConcretePrototype extends Prototype {
public ConcretePrototype(String fileName, Integer fileId, Date time) {
super(fileName, fileId, time);
System.out.println("执行构造方法============================================");
}
public void show(){
System.out.println("文件名:"+this.getFileName());
System.out.println("文件id:"+this.getFileId());
System.out.println("时间:"+this.getTime());
}
}
public class Cline {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
ConcretePrototype concretePrototype = new ConcretePrototype("学生信息文件", 0, date);
ConcretePrototype cloneA = (ConcretePrototype) concretePrototype.clone();
ConcretePrototype cloneB = (ConcretePrototype) concretePrototype.clone();
System.out.println(concretePrototype.hashCode());
System.out.println(cloneA.hashCode());
System.out.println(cloneB.hashCode());
System.out.println("===========================");
concretePrototype.show();
cloneA.show();
cloneB.show();
System.out.println("==============================");
date.setTime(999999999);
concretePrototype.show();
cloneA.show();
cloneB.show();
}
}
/*
执行构造方法============================================
356573597
1735600054
21685669
===========================
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:59:11 CST 2020
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:59:11 CST 2020
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:59:11 CST 2020
==============================
文件名:学生信息文件
文件id:0
时间:Mon Jan 12 21:46:39 CST 1970
文件名:学生信息文件
文件id:0
时间:Mon Jan 12 21:46:39 CST 1970
文件名:学生信息文件
文件id:0
时间:Mon Jan 12 21:46:39 CST 1970
*/
修改concretePrototype的属性time,cloneA和cloneB的属性一同被修改了(图中date为time)
深拷贝(深克隆)
基本类型拷贝是值传递,引用类型拷贝是开辟另一块内存地址,将原数据拷贝到新内存地址上
改变原对象的引用字段不会对副本对象的该字段有影响
深克隆代码
public class Prototype implements Cloneable {
private String fileName;
private Integer fileId;
private Date time;
@Override
protected Prototype clone() throws CloneNotSupportedException {
Object object = super.clone();
Prototype v = (Prototype) object;
v.time = (Date) this.time.clone();//将属性time格外克隆出来
return v;
}
public Prototype(String fileName, Integer fileId, Date time) {
this.fileName = fileName;
this.fileId = fileId;
this.time = time;
}
// get/set/构造方法...
}
public class ConcretePrototype extends Prototype {
public ConcretePrototype(String fileName, Integer fileId, Date time) {
super(fileName, fileId, time);
System.out.println("执行构造方法");
}
public void show(){
System.out.println("文件名:"+this.getFileName());
System.out.println("文件id:"+this.getFileId());
System.out.println("时间:"+this.getTime());
}
}
public class Cline {
public static void main(String[] args) throws CloneNotSupportedException {
String fileName = "学生信息文件";
Integer fileId = 0;
Date time = new Date();
ConcretePrototype concretePrototype = new ConcretePrototype(fileName, fileId, time);
ConcretePrototype cloneA = (ConcretePrototype) concretePrototype.clone();
ConcretePrototype cloneB = (ConcretePrototype) concretePrototype.clone();
System.out.println(concretePrototype.hashCode());
System.out.println(cloneA.hashCode());
System.out.println(cloneB.hashCode());
System.out.println("=========================");
concretePrototype.show();
cloneA.show();
cloneB.show();
System.out.println("==============================");
time.setTime(999999999);
concretePrototype.show();
cloneA.show();
cloneB.show();
}
}
/*
执行构造方法
356573597
1735600054
21685669
=========================
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:57:56 CST 2020
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:57:56 CST 2020
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:57:56 CST 2020
==============================
文件名:学生信息文件
文件id:0
时间:Mon Jan 12 21:46:39 CST 1970
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:57:56 CST 2020
文件名:学生信息文件
文件id:0
时间:Sat May 16 10:57:56 CST 2020
*/
修改concretePrototype的属性time,cloneA和cloneB的属性没有被修改,还是一开始克隆出来的值
总结
-
克隆的对象没有调用构造方法
- 上面的例子已说明
-
clone方法源码
-
protected native Object clone() throws CloneNotSupportedException;
-
发现clone方法是一个本地方法,调用clone就去本地方法库调用其他语言(c++)
-
创建实例化时,在内存中保存一份,克隆的时候直接去内存取
-
-
当这个类很复杂时,克隆就可以避免消耗资源,时间