文章目录
1.传统方式解决克隆羊问题
1.问题描述
2.类图
3.目录结构
4.代码实现
1.Sheep.java
java
复制代码
package com.sun.tradition;
/**
* Description:
* @Author sun
* @Create 2024/5/28 19:26
* @Version 1.0
*/
public class Sheep {
private String name;
private int age;
private String color;
public Sheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
2.Client.java
java
复制代码
package com.sun.tradition;
/**
* Description: 使用传统的方式复制十只羊
* @Author sun
* @Create 2024/5/28 19:26
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep6 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep7 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep8 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep9 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
System.out.println(sheep);
}
}
5.优缺点分析
2.原型模式解决克隆羊问题(浅拷贝)
1.基本介绍
2.类图
3.目录结构
4.代码实现
1.Sheep.java 实现Cloneable接口的clone方法,使用原型模式来实现克隆
java
复制代码
package com.sun.improve;
/**
* Description: 实现Cloneable接口的clone方法,使用原型模式来实现克隆
* @Author sun
* @Create 2024/5/28 19:26
* @Version 1.0
*/
public class Sheep implements Cloneable{
private String name;
private int age;
private String color;
public Sheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
@Override
protected Sheep clone() throws CloneNotSupportedException {
return (Sheep) super.clone();
}
}
2.Client.java
java
复制代码
package com.sun.improve;
/**
* Description: 原型模式的客户端
* @Author sun
* @Create 2024/5/28 19:43
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep clone = sheep.clone();
Sheep clon2 = sheep.clone();
Sheep clon3 = sheep.clone();
Sheep clon4 = sheep.clone();
System.out.println(clone);
}
}
3.原型模式在Spring框架中的源码分析
1.基本介绍
2.解释
- 在Spring中配置一个bean的时候,有一个scope属性可以选择配置prototype(原型模式)
- 当配置了这个参数,每次getBean的时候就相当于使用原型模式创建了一个新的对象,然后将原对象的属性浅拷贝到这个新的对象
4.深拷贝
1.默认的原型模式为浅拷贝
1.在Sheep.java中添加一个引用类型的数组
2.在Client.java测试克隆的羊和原来的羊的属性是不是一个数组
3.结果表明,默认的原型模式克隆出来的对象,会将引用类型的属性指向原型的属性,共享内存空间,也就是浅拷贝
2.浅拷贝与深拷贝
1.浅拷贝
2.深拷贝
5.实现深拷贝的两种方式
1.重写clone方法实现深拷贝
1.DeepCloneableTarget.java
java
复制代码
package com.sun.deepcopy01;
import java.io.Serializable;
/**
* Description: 要被深拷贝的对象,内部含有引用类型
* @Author sun
* @Create 2024/5/28 20:20
* @Version 1.0
*/
public class DeepCloneableTarget implements Serializable, Cloneable {
public static final long serialVersionUID = 1L;
private String name;
private int[] arr; // 引用类型需要手动拷贝一份
public DeepCloneableTarget(String name, int[] arr) {
this.name = name;
this.arr = arr;
}
/**
* 重写克隆方法,使当前对象可以完成深拷贝
* @return
* @throws CloneNotSupportedException
*/
@Override
protected DeepCloneableTarget clone() throws CloneNotSupportedException {
// 首先调用一次父类的克隆方法,浅拷贝一份当前对象
DeepCloneableTarget clone = (DeepCloneableTarget) super.clone();
// 目前的clone对象的arr是浅拷贝,所以需要将其手动拷贝一份
int[] copyArr = new int[arr.length];
if (arr != null) {
int j = 0;
for (int i : arr) {
copyArr[j ++] = i;
}
}
// 重新设置一下拷贝后的数组
clone.arr = copyArr;
return clone;
}
public int[] getArr() {
return arr;
}
}
2.Client.java
java
复制代码
package com.sun.deepcopy01;
import java.util.Arrays;
/**
* Description: 原型模式的客户端
* @Author sun
* @Create 2024/5/28 19:43
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
DeepCloneableTarget deepCloneableTarget = new DeepCloneableTarget("sunxiansheng", new int[]{1, 2, 3});
DeepCloneableTarget clone = deepCloneableTarget.clone();
// 测试深拷贝
System.out.println(deepCloneableTarget.getArr() == clone.getArr());
System.out.println(Arrays.toString(deepCloneableTarget.getArr()));
System.out.println(Arrays.toString(clone.getArr()));
}
}
3.结果
2.对象序列化实现深拷贝(推荐)
1.DeepCloneableTarget.java
java
复制代码
package com.sun.deepcopy02;
import java.io.*;
/**
* Description: 要被深拷贝的对象,内部含有引用类型
* @Author sun
* @Create 2024/5/28 20:20
* @Version 1.0
*/
public class DeepCloneableTarget implements Serializable, Cloneable {
public static final long serialVersionUID = 1L;
private String name;
private int[] arr;
public DeepCloneableTarget(String name, int[] arr) {
this.name = name;
this.arr = arr;
}
public int[] getArr() {
return arr;
}
// 通过对象的序列化实现深拷贝
public DeepCloneableTarget deepClone() {
// 创建流对象
ByteArrayOutputStream byteArrayOutputStream = null;
ObjectOutputStream objectOutputStream = null;
ByteArrayInputStream byteArrayInputStream = null;
ObjectInputStream objectInputStream = null;
try {
// 序列化
byteArrayOutputStream = new ByteArrayOutputStream();
// 将字节数组输出流转换为对象输出流
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
// 将当前的对象以对象流的方式输出
objectOutputStream.writeObject(this);
// 反序列化
byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
objectInputStream = new ObjectInputStream(byteArrayInputStream);
DeepCloneableTarget copyObject = (DeepCloneableTarget) objectInputStream.readObject();
return copyObject;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
// 关闭流
try {
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
if (objectOutputStream != null) {
objectOutputStream.close();
}
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
if (objectInputStream != null) {
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.Client.java
java
复制代码
package com.sun.deepcopy02;
import java.util.Arrays;
/**
* Description: 原型模式的客户端
* @Author sun
* @Create 2024/5/28 19:43
* @Version 1.0
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
DeepCloneableTarget deepCloneableTarget = new DeepCloneableTarget("sunxiansheng", new int[]{1, 2, 3});
DeepCloneableTarget clone = deepCloneableTarget.deepClone();
// 测试深拷贝
System.out.println(deepCloneableTarget.getArr() == clone.getArr());
System.out.println(Arrays.toString(deepCloneableTarget.getArr()));
System.out.println(Arrays.toString(clone.getArr()));
}
}
3.结果
3.原型模式的注意事项