第六章 原型模式

news2024/12/26 22:50:48

文章目录

  • 前言
  • 一、克隆羊问题
    • sheep类
    • clint 调用方
  • 二、引入原型模式动态克隆对象
    • sheep类
    • clint 类
  • 三、原型模式在Spring框架中源码分析
  • 四、深拷贝与浅拷贝
    • 完整代码
    • DeepCloneableTarget
    • DeepProtoType
    • Client2
  • 五、原型模式的注意事项和细节


前言


一、克隆羊问题

在这里插入图片描述

在这里插入图片描述

sheep类

package tanchishell.SJMS.prototype;

import java.util.Objects;

public class Sheep {

    private int age;

    private String name;

    private String color;

    public Sheep() {
    }

    public Sheep( String name,int age, String color) {
        this.age = age;
        this.name = name;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Sheep sheep = (Sheep) o;
        return age == sheep.age && Objects.equals(name, sheep.name) && Objects.equals(color, sheep.color);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name, color);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}


clint 调用方

package tanchishell.SJMS.prototype;

public class Client {
    public static void main(String[] args) {
// TODO Auto-generated method stub
//传统的方法
        Sheep sheep = new Sheep("tom", 1, "白色");
        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());
//.... System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
//... }
    }
}

输出

Sheep{age=1, name='tom', color='白色'}
Sheep{age=1, name='tom', color='白色'}
Sheep{age=1, name='tom', color='白色'}
Sheep{age=1, name='tom', color='白色'}

在这里插入图片描述

二、引入原型模式动态克隆对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

sheep类

package tanchishell.SJMS.prototype;

import java.util.Objects;

public class Sheep implements Cloneable {

    private int age;

    private String name;

    private String color;

    private String address = "蒙古羊";

    public Sheep friend; //是对象, 克隆是会如何处理, 默认是浅拷贝

    public Sheep() {
    }

    //克隆该实例,使用默认的 clone 方法来完成
    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }


    public Sheep(String name, int age, String color) {
        this.age = age;
        this.name = name;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", address='" + address + '\'' +
                ", friend=" + friend +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Sheep sheep = (Sheep) o;
        return age == sheep.age && Objects.equals(name, sheep.name) && Objects.equals(color, sheep.color);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name, color);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}


clint 类

package tanchishell.SJMS.prototype;

public class Client {
    public static void main(String[] args) {
        
        System.out.println("原型模式完成对象的创建");
        Sheep sheep = new Sheep("tom", 1, "白色");
        sheep.friend = new Sheep("jack", 2, "黑色");
        Sheep sheep2 = (Sheep)sheep.clone(); //克隆
        Sheep sheep3 = (Sheep)sheep.clone(); //克隆
        Sheep sheep4 = (Sheep)sheep.clone(); //克隆
        Sheep sheep5 = (Sheep)sheep.clone(); //克隆
        System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
        System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
        System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
        System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());

        System.out.println(sheep == sheep2);
    }
}

输出
原型模式完成对象的创建
sheep2 =Sheep{age=1, name='tom', color='白色', address='蒙古羊', friend=Sheep{age=2, name='jack', color='黑色', address='蒙古羊', friend=null}}sheep2.friend=102206883
sheep3 =Sheep{age=1, name='tom', color='白色', address='蒙古羊', friend=Sheep{age=2, name='jack', color='黑色', address='蒙古羊', friend=null}}sheep3.friend=102206883
sheep4 =Sheep{age=1, name='tom', color='白色', address='蒙古羊', friend=Sheep{age=2, name='jack', color='黑色', address='蒙古羊', friend=null}}sheep4.friend=102206883
sheep5 =Sheep{age=1, name='tom', color='白色', address='蒙古羊', friend=Sheep{age=2, name='jack', color='黑色', address='蒙古羊', friend=null}}sheep5.friend=102206883


false


三、原型模式在Spring框架中源码分析

在使用 xml 配置 bean 时,可以选择参数 scope = ”prototype“ 来确定使用 原型模式还是单例模式,会调用到 dogetBean 方法,先判断参数是否需要使用单例模式,如果不成立会去判断 是否需要使用原型模式 else if ( mbd . isPrototype) 进行原型模式的业务逻辑

在这里插入图片描述

先进入 applictionContext 的 getBean 方法

在这里插入图片描述

进入 getBean 会先进入 assertBeanFactoryActive()方法,然后进入getBeanFactory( ),里面是同步代码块同步获取Bean工厂,从getBeanFactory( ) 方法出来后进入 getBean( ) 方法,就会尝试在工厂里面获取一个 bean 对象,genBean 会调用到 doget Bean()方法

在这里插入图片描述

会先判断是否为 单例模式,是不是需要创建单例对象

在这里插入图片描述

然后 else if 判断是否需要配置原型模式,条件成立后,会调用到 creatBean()方法返回一个原型实例

在这里插入图片描述

四、深拷贝与浅拷贝

从上面的输出结果我们就可以看出,克隆羊的时候,它的朋友是没有被克隆的,所以是浅拷贝,如果想要达到深拷贝的效果,可以通过实现 克隆接口和序列化接口来实现

在这里插入图片描述
在这里插入图片描述

完整代码

DeepCloneableTarget

package tanchishell.SJMS.prototype;

import java.io.Serializable;
import java.util.Objects;

public class DeepCloneableTarget implements Serializable, Cloneable {
    private static final long serialVersionUID = 1L;
    private String cloneName;
    private String cloneClass;
    //构造器
    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }
    //因为该类的属性,都是 String , 因此我们这里使用默认的 clone 完成即可
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

DeepProtoType

package tanchishell.SJMS.prototype;

import java.io.*;
import java.util.Objects;

public class DeepProtoType implements Serializable, Cloneable{

    public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型

    public DeepProtoType() {
        super();
    }

    //深拷贝 - 方式 1 使用 clone 方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object deep = null;
        //这里完成对基本数据类型(属性)和 String 的克隆
        deep = super.clone();
        //对引用类型的属性,进行单独处理
        DeepProtoType deepProtoType = (DeepProtoType) deep;

        Object clone = deepCloneableTarget.clone();
        deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();

        //通过强制类型转换创建了新的对象,改变了内存地址
        System.out.println(deepProtoType.deepCloneableTarget.hashCode() +" =====  "+ clone.hashCode());
        return deepProtoType;
    }

    //深拷贝 - 方式 2 通过对象的序列化实现 (推荐)
    public Object deepClone() {
        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType) ois.readObject();
            return copyObj;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }
}


Client2

package tanchishell.SJMS.prototype;

public class Client2 {
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        DeepProtoType p = new DeepProtoType();
        p.name = "宋江";
        p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");
        //方式 1 完成深拷贝
//        DeepProtoType p2 = (DeepProtoType) p.clone();
//        DeepProtoType p3 = (DeepProtoType) p.clone();
//        DeepProtoType p4 = (DeepProtoType) p.clone();
//
//        System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
//        System.out.println("p2.name=" + p2.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
//        System.out.println("p3.name=" + p3.name + "p3.deepCloneableTarget=" + p3.deepCloneableTarget.hashCode());
//        System.out.println("p4.name=" + p4.name + "p3.deepCloneableTarget=" + p4.deepCloneableTarget.hashCode());
        //方式 2 完成深拷贝
        DeepProtoType p2 = (DeepProtoType) p.deepClone();
        System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
        System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
    }
}

五、原型模式的注意事项和细节

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/448340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql查询字段未加引号问题及隐式转换

1. 问题重现 最近线上出了个问题,用户明明没有投票,却提示已投票,我查询数据,刚开始没有查出数据,后来却查出数据了,以为没有问题,后来以为是插入的时候通过int类型插入,导致varcha…

美国最大公共养老基金之一Strs Ohio不断增持IonQ股票

​ (图片来源:网络) 截至2022年12月31日第四季度末,美国最大的公共养老基金之一Strs Ohio发布报告称,其一直在增持IonQ,Inc.(纽约证券交易所代码:IONQ)的股份。资产管理公…

如何在云服务器/云主机上部署最新版本的Hadoop3.3.5(Ubuntu20.0.4)

在云服务器上部署Hadoop 步骤1:更新系统 sudo apt-get update sudo apt-get upgrade步骤2:安装Java Hadoop需要Java运行环境。首先,安装OpenJDK 8: sudo apt-get install openjdk-8-jdk检查Java版本: java -versi…

上海车展:比亚迪宋L概念车全球首发,这是要硬扛特斯拉?

纵观2023年的新能源汽车市场,特斯拉可以说当仁不让地成为了全球最为“吸睛”的车企之一。凭借一系列令无数人瞠目结舌的降价举措,特斯拉给全球汽车市场带来了强烈冲击。虽然特斯拉上海工厂已经接近满负荷运转,但是面对雪片般飞来的订单依然供…

SpringBoot设置动态定时任务

SpringBoot设置动态定时任务 1.准备工作 搭建SpringBoot工程 引入相关依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><depende…

ROS学习第八节——话题通信自定义msg

1.介绍 在 ROS 通信协议中&#xff0c;数据载体是一个较为重要组成部分&#xff0c;ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty.... 但是&#xff0c;这些数据一般只包含一个 data 字段&#xff0c;结构的单一意味着功能上的…

Java基础(九)多线程

我们之前学习的程序在没有跳转语句的情况下&#xff0c;都是由上至下沿着一条路径依次执行。现在想要设计一个程序&#xff0c;可以同时有多条执行路径同时执行。比如&#xff0c;一边游戏&#xff0c;一边qq聊天&#xff0c;一边听歌&#xff0c;怎么设计&#xff1f; 要解决…

每日一个小技巧:今天告诉你拍照识别文字的软件有哪些

在现代社会里&#xff0c;手机已经成为了人们生活中必不可少的工具。它的功能众多&#xff0c;比如通讯、上网、拍照以及导航等&#xff0c;为我们的生活带来了许多便利。除此之外&#xff0c;手机还能帮助我们解决一些实际的问题&#xff0c;例如&#xff0c;当你需要识别图片…

Spring Aop详解汇总

文章目录 近期想法什么是AOPSpringAOP与AspectjSpringAOP体系概述概念详解连接点- Jointpoint切入点- Pointcut通知- Advice切面- Aspect织入- Weaving 实现原理—动态代理JDK动态代理描述原理代码示例注意执行结果 优点缺点 CGLib动态代理描述原理代码示例注意执行结果 优点缺…

ChatGPT会凉吗?巴菲特、马斯克呼吁暂停

ChatGPT 迅速“风靡”全球&#xff0c;无疑成为了人工智能领域备受瞩目的“明星产品”&#xff0c;然而随着 ChatGPT 应用越来越广泛&#xff0c;陆续爆出被用于学术造假、制作黑客武器以及泄露用户敏感聊天信息等一系列负面新闻。至此&#xff0c;社会开始重新审视类似 ChatGP…

图像傅里叶变换以及频谱中心化

图像的空域滤波&#xff1a; I ∗ G I*G I∗G 矩阵 I I I与一个小矩阵 G G G进行卷积 图像的频域滤波&#xff1a; F − 1 [ F [ I ] H ] F^{-1}[F[I]\times H] F−1[F[I]H] 矩阵 I I I的傅里叶变换与同样大小的矩阵 H H H进行对应元素相乘&#xff0c;然后将结果通过逆傅里…

并查集解决图的连通性问题

并查集 1. 定义2.并查集3.模板代码4. 力扣例题4.1 剑指 Offer II 118. 多余的边4.2 力扣695. 岛屿的最大面积 1. 定义 在计算机科学中&#xff0c;并查集&#xff08;英文&#xff1a;Disjoint-set data structure&#xff0c;直译为不交集数据结构&#xff09;是一种数据结构&…

卷积神经网络轻量化教程之通道剪枝【附代码】

这两天自己手写了一个可以简单实现通道剪枝的代码&#xff0c;在这篇文章中也会对代码进行讲解&#xff0c;方便大家在自己代码中的使用。 如果还想学习YOLO系列的剪枝代码&#xff0c;可以参考我其他文章&#xff0c;下面的这些文章都是我根据通道剪枝的论文在YOLO上进行的实…

React框架----路由管理

文章目录 SPA路由路由基本使用路由组件与一般组件NavLink SPA single page application只有一个页面异步请求数据&#xff0c;局部更新页面本地局部切换页面&#xff08;不会向服务端加载整个页面&#xff09; 路由 地址栏路径与组件的对应关系切换路径&#xff0c;则切换组…

YOLOv5+单目跟踪(python)

YOLOv5单目跟踪&#xff08;python&#xff09; 1. 目标跟踪2. 测距模块2.1 设置测距模块2.2 添加测距 3. 主代码4. 实验效果 相关链接 1. YOLOv5单目测距&#xff08;python&#xff09; 2. YOLOv7单目测距&#xff08;python&#xff09; 3. YOLOv7单目跟踪&#xff08;pytho…

JDBC详解(一):JDBC概述

JDBC概述 前言一、数据的持久化1、概念2、应用 二、Java中的数据存储技术三、JDBC介绍四、JDBC体系结构五、JDBC程序编写步骤 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注博主&#xff01;也许一个人独行&#…

全志 Orange Pi相关网站集

Orange Pi 系统安装的常识 看到有教程说android系统需要用win32diskimager才能成功烧写运行镜像名称与版本的对应关系 ubuntu版本号代号16.04Xenial Xerus&#xff08;好客的非洲地鼠&#xff09;18.04Bionio Beaver &#xff08;仿生海狸}20.04Focal Fossa &#xff08;类似…

DFIG控制10-b: 双馈发电机的转矩方程推导

DFIG控制10-b 双馈发电机的转矩方程推导 接上DFIG控制10&#xff1a; 双馈发电机的动态模型_Fantasy237的博客&#xff0c;DFIG的转矩方程和推导。 &#xff08;字数限制&#xff0c;只能放在新的一篇博文里了。。&#xff09; 转矩方程 定子αβ静止坐标系 从三相坐标系下…

Linux网络套接字(二)

学习任务&#xff1a; 继网络套接字&#xff08;一&#xff09;&#xff0c;继续学习套接字socket编程接口&#xff08;已经学习了socket和bind&#xff09;&#xff0c;实现TCP客户端/服务器(单连接版本, 多进程版本, 多线程版本&#xff0c;进程或线程池版本)&#xff0c;并且…

JavaScript(JS)-1.JS基础知识

1.JavaScript概念 (1)JavaScript是一门跨平台&#xff0c;面向对象的脚本语言&#xff0c;来控制网页行为的&#xff0c;它能使网页可交互 (2)W3C标准&#xff1a;网页主要由三部分组成 ①结构&#xff1a;HTML负责网页的基本结构&#xff08;页面元素和内容&#xff09;。 …