原型(克隆)模式

news2024/10/6 6:49:34

文章目录

    • 思考原型(克隆)模式
      • 1.原型模式的本质
      • 2.何时选用原型模式
      • 3.优缺点
      • 4.实现
        • 原型模式(浅克隆)
        • 原型模式(深克隆)
        • java浅克隆
        • java深克隆

思考原型(克隆)模式

原型模式顾名思义通过一个接口实现快速创建对象

1.原型模式的本质

原型模式的本质:克隆生成对象。

克隆是手段,目的是生成新的对象实例。正是因为原型的目的是为了生成新的对象实例,原型模式通常是被归类为创建型的模式。

原型模式也可以用来解决“只知接口而不知实现的问题”,使用原型模式,可以出现一种独特的“接口造接口”的景象,这在面向接口编程中很有用。同样的功能也可以考虑使用工厂来实现。

另外,原型模式的重心还是在创建新的对象实例,至于创建出来的对象,其属性的值是否一定要和原型对象属性的值完全一样,这个并没有强制规定,只不过在目前大多数实现中,克隆出来的对象和原型对象的属性值是一样的。

也就是说,可以通过克隆来创造值不一样的实例,但是对象类型必须一样。可以有部分甚至是全部的属性的值不一样,可以有选择性地克隆,就当是标准原型模式的一个变形使用吧。

2.何时选用原型模式

建议在以下情况时选用原型模式。

  • 如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统只面向接口编程,在系统需要新的对象的时候,可以通过克隆原型来得到。
  • 如果需要实例化的类是在运行时刻动态指定时,可以使用原型模式,通过克隆原型来得到需要的实例。

3.优缺点

原型模式的优点

  • 对客户端隐藏具体的实现类型
    原型模式的客户端只知道原型接口的类型,并不知道具体的实现类型,从而减少了客户端对这些具体实现类型的依赖。

  • 在运行时动态改变具体的实现类型
    原型模式可以在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改变具体的实现类型,看起来接口没有任何变化,但其实运行的已经是另外一个类实例了。因为克隆一个原型就类似于实例化一个类。

原型模式的缺点

  • 原型模式最大的缺点就在于每个原型的子类都必须实现 clone 的操作,尤其在包含引用类型的对象时,clone方法会比较麻烦,必须要能够递归地让所有的相关对象都要正确地实现克隆。

4.实现

原型模式(浅克隆)

克隆接口

/**
 * @description:需要克隆方法实现此接口
 */
public interface OrderApi {

    /**
     * 克隆方法
     * @return
     */
    OrderApi clone();
}

实现类

/**
 * @description:个人订单
 */
@Data
@ToString
public class PersonOrder implements OrderApi{

    /**
     * 用户名
     */
    private String personName;
    /**
     * 产品id
     */
    private Integer productId;

    private CompanyOrder companyOrder;


    /**
     * 克隆对象
     * @return
     */
    @Override
    public OrderApi clone() {
        PersonOrder personOrder = new PersonOrder();
        personOrder.setPersonName(this.personName);
        personOrder.setProductId(this.productId);
        //引用对象克隆
        personOrder.setCompanyOrder(this.companyOrder);
        return personOrder;
    }
}

/**
 * @description:公司订单
 */
@Data
@ToString
public class CompanyOrder implements OrderApi{

    /**
     * 公司名
     */
    private String companyName;
    /**
     * 产品id
     */
    private Integer productId;

    /**
     * 克隆对象
     * @return
     */
    @Override
    public OrderApi clone() {
        CompanyOrder companyOrder = new CompanyOrder();
        companyOrder.setCompanyName(this.companyName);
        companyOrder.setProductId(this.productId);
        return companyOrder;
    }
}

测试类

/**
 * @description:测试类
 */
public class Client {

    public static void main(String[] args) {

        PersonOrder personOrder = new PersonOrder();
        personOrder.setPersonName("张三");
        personOrder.setProductId(10001);

        CompanyOrder companyOrder = new CompanyOrder();
        companyOrder.setCompanyName("字节跳动");
        companyOrder.setProductId(10002);
        personOrder.setCompanyOrder(companyOrder);

        System.out.println("原对象:"+personOrder);
        //自己实现克隆
        OrderApi personClone = personOrder.clone();

        System.out.println("克隆对象:"+personClone);
        //修改原对象中引用对象的值
        companyOrder.setCompanyName("88888888888");
        System.out.println("克隆对象:"+personClone);
    }
}

结果
在这里插入图片描述

原型模式(深克隆)

实现深度克隆只需克隆引用对象时,调用它自己的克隆方法,一直传递下去

/**
 * 克隆对象
 * @return
 */
@Override
public OrderApi clone() {
    PersonOrder personOrder = new PersonOrder();
    personOrder.setPersonName(this.personName);
    personOrder.setProductId(this.productId);
    personOrder.setCompanyOrder((CompanyOrder) this.companyOrder.clone());
    return personOrder;
}

结果
在这里插入图片描述

java提供的克隆

1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)
2、深克隆:深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。

java浅克隆

1.实现Cloneable接口
2.重写clone方法

/**
 * @description:个人订单
 */
@Data
@ToString
public class PersonOrder2 implements Cloneable{

    /**
     * 用户名
     */
    private String personName;
    /**
     * 产品id
     */
    private Integer productId;

    private CompanyOrder2 companyOrder2;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

@Data
@ToString
public class CompanyOrder2 implements Cloneable{

    /**
     * 公司名
     */
    private String companyName;
    /**
     * 产品id
     */
    private Integer productId;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

测试

/**
 * @description:测试类
 */
public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {

        CompanyOrder2 companyOrder2 = new CompanyOrder2();
        companyOrder2.setCompanyName("字节跳动");
        companyOrder2.setProductId(10002);

        PersonOrder2 personOrder2 = new PersonOrder2();
        personOrder2.setPersonName("张三");
        personOrder2.setProductId(10001);
        personOrder2.setCompanyOrder2(companyOrder2);
        System.out.println("原对象:"+personOrder2);

        //java浅克隆
        Object clone = personOrder2.clone();
        System.out.println("克隆对象:"+clone);
        companyOrder2.setCompanyName("9999999999");
        System.out.println("克隆对象:"+clone);

    }
}

结果
在这里插入图片描述

可以看到,虽然克隆出来了一个一模一样的对象,但是修改原对象的属性,克隆的对象属性也改变了,这就是浅克隆,原对象和克隆对象的引用属性共同指向一个内存地址

java深克隆

实现深度克隆只需克隆引用对象时,调用它自己的克隆方法,一直传递下去,原理和上面的原型实现深克隆一样

@Override
protected Object clone() throws CloneNotSupportedException {
    PersonOrder2 clone = (PersonOrder2) super.clone();
    clone.setCompanyOrder2((CompanyOrder2) this.companyOrder2.clone());
    return clone;
}

结果
在这里插入图片描述

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

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

相关文章

【Ubuntu】进程与线程编程实验

文章目录进程与线程实验一:创建进程基础版:创建父子线程 fork基础版:父子线程交替运行基础版:创建进程 文件写入练习版:创建线程 子读父阻塞实验二:线程共享进程中的数据实验三:多线程实现单词统…

总结709(bug集合)

今天不知道怎么了,那个曾弄了我20多天的冒险模块,在今天,差不多要完工了。弄出的那一刻,有的是喜悦,但之后,更多的是叹气。 也就是从此刻我才意识到,我曾自认为很崇高的职位,可能事…

传奇出现黑屏卡屏不动是怎么回事

在写这篇文章之前,先给给大家说一下,这篇文章写的是出现黑屏、卡屏不动是我们玩传奇的时候出现的,而不是在架设传奇时候出现的,所以要特别是注意一下,架设和玩出现黑屏是完全不一样的,所以解决方案也不一样…

驱动开发 platfrom总线驱动的三种方式

驱动的分隔与分离: 对于 Linux 这样一个成熟、庞大、复杂的操作系统,代码的重用性非常重要,在驱动程序,因为驱动程序占用了 Linux 内核代码量的大头,如果不对驱动程序加以管理,任由重复的代码肆意增加&…

基于深度学习的合成孔径雷达自聚焦

文章目录引言什么是合成孔径雷达什么是自聚焦经典自聚焦方法基于机器学习的方法基于极速学习机的方法基于深度学习的SAR自聚焦代码附录引言 本文全面介绍合成孔径雷达自聚焦概念和方法。想获取更为详尽的描述,请参考以下几篇论文, 如果数据或代码对你的研究有用&am…

【ASM】字节码操作 工具类与常用类 ClassRemapper 介绍 类映射 代码混淆

文章目录 1.概述2. ClassRemapper#2.1 class info2.2 fields2.3 构造方法2.4 method3. 案例3.1 案例1-修改类名3.2 案例2-修改字段名和方法3.3 案例3-修改2个类4.总结1.概述 在上一篇文章:【ASM】字节码操作 工具类与常用类 InstructionAdapter 介绍 我们知道了,对于Instruc…

[思维模式-5]:《如何系统思考》-1- 认识篇 - 总体结构与知识框架

目录 前言: 第一篇:认知篇 第1章 无所不在的系统 // 2 第2章 思维的转变 // 30 第二篇:方法与工具 第3章 深入思考 // 50 第4章 动态思考 // 78 第5章 全面思考 // 109 第6章 系统思考的“新语言”:因果回路图 // …

Zookeeper(一)- Zookeeper介绍与集群部署

文章目录一、Zookeeper 介绍1. Zookeeper概述2. Zookeeper工作机制3. Zookeeper特点4. Zookeeper数据结构5. Zookeeper应用场景(1)统一命名服务(2)统一配置管理(3)统一集群管理(4)服…

翻译QT使用手册:将库添加到项目

将库添加到项目 除了 Qt 库之外,您还可以将其他库添加到您的项目中。该过程取决于图书馆的类型和位置。您可以添加系统库、您自己的库或第三方库。该库可以位于当前项目的构建树中,也可以位于另一个构建树中。 将库添加到项目 除了 Qt 库之外&#xff0c…

远距离双目视觉测量系统纵深方向测量精度较低原因分析

两台相机基线距离约1200mm,对20m外的一个LED发光点进行持续观测,效果如下视频所示: 可见ZZZ方向的重复性精度比较差,波动量甚至多于2mm了,而以10mm导轨基准距离为基准,精度测试结果也比较差,如…

[附源码]计算机毕业设计springboot个性化产品服务管理系统论文

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

xss-labs/level11

首先输入 <script>alert(xss)</script> 丝毫不差 没有出现回弹现象 根本就不出人意料好吧 接着来看一下源代码好吧 能够看得出来第一个输出点由于htmlspecialchars转义操作 所以上述代码根本行不通 这一关比上一关又多了一个隐藏表单 一共是有四个隐藏表单 从…

C++入门笔记

C 入门笔记Functions in CC header Files下面主要是我学习C的一个笔记&#xff0c;记录学习中遇到的一些重点事项。下面是视频的连接https://www.bilibili.com/video/BV1Ay4y1i7Z6/?p10&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourcee6e…

单连通图的判断

单连通图的判断算法&#xff1a; &#xff08;1&#xff09;对每个点进行dfs得到一棵dfs树&#xff1b; &#xff08;2&#xff09;判断是否存在前向边和横向边&#xff0c;若有则必定存在两个点之间有至少2条简单路径&#xff0c;因此该图不属于单连通图&#xff1b; &#xf…

一个开源且完全自主开发的国产网络协议栈

已剪辑自: https://mp.weixin.qq.com/s/_1LE7mGc9mRuajRgNsyirQ onps是一个开源且完全自主开发的国产网络协议栈&#xff0c;适用于资源受限的单片机系统&#xff0c;提供完整地ethernet/ppp/tcp/ip协议族实现&#xff0c;同时提供sntp、dns、ping等网络工具&#xff0c;支持以…

mac pro M1(ARM)安装:.Net、C#开发环境

0.引言 因为.Net是开发、运行环境&#xff0c;而C#是一个编程语言&#xff0c;专用于.Net平台&#xff0c;C#是运行在.Net之上的&#xff0c;所以两者的安装是密不可分的 1. 安装 1、因为arm架构安装Visual Studio 2022 for mac可以自动附带安装.Net&#xff0c;所以我们只需…

刷题之完全二叉树的权值和小字辈及根据后序和中序遍历输出先序遍历

1、完全二叉树的权值 1&#xff09;题目 给定一棵包含 N 个节点的完全二叉树&#xff0c;树上每个节点都有一个权值&#xff0c;按从 上到下、从左到右的顺序依次是 A1, A2, AN&#xff0c;如下图所示&#xff1a; 现在小明要把相同深度的节点的权值加在一起&#xff0c;他想…

开关电源32个检测项目、检测方法与检测设备(下)

开关电源是电器必备&#xff0c;本文详细介绍了开关电源的32个常见检测项目、检测方法与仪器&#xff0c;内容较多&#xff0c;前些日子介绍了上部分16个项目&#xff08;点击阅读&#xff09;&#xff0c;今天介绍剩下的16个项目。抱歉久等了&#xff01; 过压保护测试 一、目…

MySQL数据库事务控制

目录 一、事务控制概念 二、事务控制特性 三、事务控制相关命令 1、测试begin和commit&#xff08;开始事务和提交事务&#xff09; 2、测试事务回滚rollback 四、总结 1、事务的ACID特性 2、事务之间的相互影响 3、事务的隔离级别 一、事务控制概念 在MySQL中用于处理…

上海大治河二线船闸总体设计与结构计算

目录 第一章 设计基本资料 1 1.1工程概况 1 1.2 货运量预测 1 1.3 建筑物设计等级 1 1.4 通航情况及计算参数的选取 1 1.5 设计船型 2 1.6 特征水位表 2 1.7 水文气象资料 3 1.8 工程地质 3 第二章 总体设计 4 2.1 船闸地理位置确定 4 2.2 船闸线、级数确定 5 2.3 船闸的基本尺…