设计模式-原型模式

文章目录

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.原型模式的注意事项
相关推荐
带刺的坐椅14 分钟前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看2 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程2 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t2 小时前
ZIP工具类
java·zip
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan3 小时前
第10章 Maven
java·maven
百锦再4 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说4 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多4 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再4 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven