概念:
原型模式是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而无需通过标准构造函数来创建。在原型模式中,新对象的创建是通过克隆现有对象而实现的,因此它是基于原型对象的复制而创建新对象的。
在Java中,原型模式通常通过实现 Cloneable 接口和重写 clone() 方法来实现。Cloneable 接口是一个标记接口,它指示了该类的实例可以被克隆。然后,通过重写 clone() 方法来实现对象的克隆。
换一个方式理解
:
原型模式就像是制作复印件一样。假设你有一份文件,想要多份一模一样的,但是你又不想重新从头写一遍。这时候,你可以使用原型模式:先制作一份原始文件,然后通过复制这份原始文件,就可以得到多份完全相同的副本。
代码1:
/**
* 怎么实现克隆。拷贝?
* 1、实现一个接口:
* 2、重写一个方法
*/
public class Video implements Cloneable{//克隆视频
private String name;
private Date createTime;
/**
* 重写克隆方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
public Video() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
}
我们这有一个视频类。实现了Cloneable
接口并重写clone()
方法。这个clone()方法调用父类的克隆方法。而这个父类中的clone()是在本地克隆
测试类
import java.util.Date;
/**
* 客户端。实现克隆
*/
public class BiliBiliClient {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
//需要一个原型对象实现克隆
//原型对象叫做v1
Video v1 = new Video("Java从入门到精通", date);
System.out.println("v1=====>"+v1);
System.out.println("v1.hashCode=====>"+v1.hashCode());
//v1可以克隆v2
Video v2 = (Video) v1.clone();
System.out.println("v2=====>"+v2);
System.out.println("v2.hashCode=====>"+v2.hashCode());
//修改v2的值
v2.setName("张三");
System.out.println(v2);
}
}
创建一个BliBlili客户端类实现克隆,首先,我们先把原型对象创建出来,v1
的hashCode输出。我们在想创建一个v2对象的时候,传统的方式是不是还需要new Video对象,但是现在我们可以直接使用v1.clone()
方法进行创建,返回的是一个Object类。强制转换成Video对象。在进行把克隆的内容V2进行输出。此时两个对象内容一样,但是hashCode不一样
测试结果:
问题:
V2对象是V1对象拷贝过来的。但是他们还是指向同一个地址。
验证:
修改客户端的代码:
import java.util.Date;
/**
* 客户端。实现克隆
*/
public class BiliBiliClient {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
//需要一个原型对象实现克隆
//原型对象叫做v1
Video v1 = new Video("Java从入门到精通", date);
Video v2 = (Video) v1.clone();
System.out.println("v1原始的值:=====>"+v1);
System.out.println("v2原始的值:=====>"+v2);
//修改后的值,把date数值改变一下
System.out.println("==================================");
date.setTime(12345678);
System.out.println("v1修改后的:=====>"+v1);
System.out.println("v2修改后的:=====>"+v2);
//
//
// System.out.println("v1.hashCode=====>"+v1.hashCode());
// //v1可以克隆v2
//
// System.out.println("v2=====>"+v2);
// System.out.println("v2.hashCode=====>"+v2.hashCode());
// //修改v2的值
// v2.setName("张三");
// System.out.println(v2);
}
}
此时我们修改V1的值。上图所示,我们v1指向的是data。但是v2是v1克隆出来的。地址值是没有变化的。所以这是浅克隆。
测试结果:
我们理想的情况是:深度克隆
地址也会完全变化的。最简单的一种就是改造克隆的方法、修改原型类中的克隆方法实现深度克隆:
代码2:
package com.MrSun.PrototypeTest.demo02;
import java.util.Date;
public class Video implements Cloneable{
private String name;
private Date createTime;
/**
* 重写克隆方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();//深度克隆
Video v=(Video) obj;
//将这个对象的属性也进行克隆
v.createTime= (Date) this.createTime.clone();
return obj;
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
public Video() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
}
主要就修改了cole方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();//深度克隆
Video v=(Video) obj;
//将这个对象的属性也进行克隆
v.createTime= (Date) this.createTime.clone();
return obj;
}
我们对里面的属性也进行克隆。这样就可以实现深度克隆、
验证:
加油!!!!!!!!!!