【设计模式-04】原型模式

【设计模式-04】原型模式

  • 1. 概述
  • 2. 结构
  • 3. 实现
  • 4. 案例
  • 5. 使用场景
  • 6. 优缺点
    • 6.1 原型模式的优点
    • 6.2 原型模式的缺点
  • 7. 实现深克隆(深拷贝)

1. 概述

原型模式: 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

2. 结构

原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的 clone() 方法。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

接口类图如下:

在这里插入图片描述

3. 实现

原型模式的克隆分为浅克隆深克隆

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。

深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

Java中的Object类中提供了 clone() 方法来实现浅克隆。 Cloneable 接口是上面的类图中的抽象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。代码如下:

Realizetype(具体的原型类):

public class Realizetype implements Cloneable {public Realizetype() {
        System.out.println("具体的原型对象创建完成!");
    }@Override
    protected Realizetype clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");
        return (Realizetype) super.clone();
    }
}

client(测试访问类):

package com.itheima.pattern.prototype.demo;

/**
 * @version v1.0
 * @ClassName: client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class client {
    public static void main(String[] args) throws CloneNotSupportedException {
        //创建一个原型类对象
        Realizetype realizetype = new Realizetype();

        //调用Realizetype类中的clone方法进行对象的克隆
        Realizetype clone = realizetype.clone();

        System.out.println("原型对象和克隆出来的是否是同一个对象?" + (realizetype == clone));
    }
}

结果: false

在这里插入图片描述

4. 案例

用原型模式生成“三好学生”奖状。

同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个“三好学生”奖状出来,然后在修改奖状上的名字即可。

类图如下:
在这里插入图片描述

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: Citation
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class Citation implements Cloneable {

    /*//三好学生上的姓名
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }*/
    private Student stu;

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    public Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }

    public void show() {
        System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
}

上面这个是浅拷贝,如果要深拷贝按照如下这种方式实现:

import java.util.ArrayList;
import java.util.List;

// 原型接口
public interface Prototype extends Cloneable {
    Prototype clone();
}

// 具体原型类
public class ConcretePrototype implements Prototype {
    private List<String> fields;

    public ConcretePrototype(List<String> fields) {
        this.fields = fields;
    }

    public void setFields(List<String> fields) {
        this.fields = fields;
    }

    public List<String> getFields() {
        return fields;
    }

    @Override
    public Prototype clone() {
        try {
            ConcretePrototype cloned = (ConcretePrototype) super.clone();
            cloned.fields = new ArrayList<>(this.fields); // 深拷贝
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototype{fields=" + fields + "}";
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        List<String> fieldList = new ArrayList<>();
        fieldList.add("Field1");
        fieldList.add("Field2");

        ConcretePrototype prototype1 = new ConcretePrototype(fieldList);
        ConcretePrototype prototype2 = (ConcretePrototype) prototype1.clone();

        prototype2.getFields().add("Field3");

        System.out.println(prototype1);
        System.out.println(prototype2);
    }
}

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: Student
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class Student {

    //学生的姓名
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

package com.itheima.pattern.prototype.test;

/**
 * @version v1.0
 * @ClassName: CitaionTest
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class CitaionTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        //1,创建原型对象
        Citation citation = new Citation();
        //创建张三学生对象
        Student stu = new Student();
        stu.setName("张三");
        citation.setStu(stu);

        //2,克隆奖状对象
        Citation citation1 = citation.clone();
        Student stu1 = citation1.getStu();
        stu1.setName("李四");

        /*citation.setName("张三");
        citation1.setName("李四");*/

        //3,调用show方法展示
        citation.show();
        citation1.show();
    }
}

5. 使用场景

  • 性能和安全要求比较高。
  • 原型模式适用于创建复杂对象,避免了每次都从头开始构建对象的开销。在实际应用中,经常结合其他设计模式一起使用,如工厂模式,进一步简化对象的创建和管理。

6. 优缺点

6.1 原型模式的优点

  1. 性能优越:通过克隆现有对象创建新对象,比直接实例化对象更高效,特别是对于创建代价高的对象。
  2. 简化对象创建过程:隐藏对象的创建过程,使得代码更加简洁和易读。
  3. 灵活性:可以在运行时动态创建和配置对象,而不依赖于具体类。

6.2 原型模式的缺点

  1. 浅拷贝问题:如果对象包含引用类型的字段,默认的 clone() 方法只会进行浅拷贝,需要手动实现深拷贝。
  2. 实现复杂:对于复杂对象,需要实现复杂的深拷贝逻辑,容易出错。

7. 实现深克隆(深拷贝)

  1. 实现Cloneable接口并重写clone方法:需要手动处理深拷贝逻辑,适合对性能要求较高的场景。
  2. 使用序列化:实现较为简单,但对性能有一定影响,适合对象比较复杂的场景。
  3. 使用第三方库:如Apache Commons Lang的SerializationUtils,方便快捷,适合大多数场景。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VSCode常用的一些插件

Chinese (Simplified) 汉语&#xff08;简体&#xff09;拓展包。 Auto Close Tag 可以自动增加xml/html的闭合标签。 CodeSnap 截图神器。截图效果在下面。 Dracula Official vscode一个很好看的主题。 Git Graph git管理工具。 GitHub Repositories 有了它&#xff0c;不…

基于Vue+ElementUI框架实现学生管理系统前端页面设计

目录 一. 最终效果展示 二. 详细教程 1. 创建项目 2. 下载组件 3. 在main.js中配置 4. 创建项目中的组件(页面) 登录组件 Login.vue 系统主页组件 Main.vue 学生管理组件 StudentList.vue 专业管理组件 MajorList.vue 5. 在index.js中配置组件路由 6. 添加画布 三…

【PyQt5】一文向您详细介绍 QVBoxLayout() 的作用

【PyQt5】一文向您详细介绍 QVBoxLayout() 的作用 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&a…

算法金 | 没有思考过 Embedding,不足以谈 AI

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 在当今的人工智能&#xff08;AI&#xff09;领域&#xff0c;Embedding 是一个不可或缺的概念。如果你没有…

第六篇:精通Docker Compose:打造高效的多容器应用环境

精通Docker Compose&#xff1a;打造高效的多容器应用环境 1. 引言 1.1 目的与重要性 在现代软件开发中&#xff0c;随着应用程序的复杂性不断增加&#xff0c;传统的单一容器部署方式已无法满足需求。Docker Compose作为一种强大的工具&#xff0c;专门用于定义和运行多容器…

用户中心项目全流程

企业做项目流程 需求分析 > 设计&#xff08;概要设计 、 详细设计&#xff09; > 技术选型 >初始化项目 / 引入需要的技术 > 写个小demo > 写代码 &#xff08;实现业务逻辑&#xff09; > 测试&#xff08;单元测试&#xff09;> 代码提交 / 代码评审 …

【C++:list】

list概念 list是一个带头的双向循环链表&#xff0c;双向循环链表的特色&#xff1a;每一个节点拥有两 个指针进行维护&#xff0c;俩指针分别为prev和next,prev指该节点的前一个节点&#xff0c;next为该节点的后一个节点 list的底层实现中为什么对迭代器单独写一个结构体进行…

Toco x Databend:Databend Cloud 如何满足 Web3 大数据服务的严苛考验?

Toco 是一家位于瑞士的 Web3 服务提供商&#xff0c;致力于通过彻底改变全球金融体系的陈旧观念来应对气候变化。他们提供了一种开创性的碳货币 Tocos&#xff0c;每个流通中的 Tocos 代表一吨二氧化碳当量&#xff0c;存储在安全可靠的数字钱包中。用户可以使用 Tocos 应用轻松…

Jmeter+InfluxDB+Grafana性能测试数据展示

JmeterInfluxDBGrafana提供了一种更好的对Jmeter压测结果的实时监控展示。可以理解为数据源产生的数据加上时间记录并存储&#xff0c;然后使用各种开源图表组件进行展示。实现jmeter报告的更好的可视化展示 1&#xff09;方便测试结果数据落地以及更好的分析 2&#xff09;将…

计算机视觉-期末复习-简答/名词解释/综合设计

目录 第一讲--计算机/机器视觉概述 名词解释 简答 第二讲--图像处理概述 名词解释 简答 第三讲没划重点习题 第四讲--特征提取与选择 名词解释 简答 综合题 第五讲--不变特征 名词解释 简答 第六讲--物体分类与检测 简答 综合题 第七讲--视觉注意机制 简答 …

鸿蒙期末项目(完结)

两天仅睡3个小时的努力奋斗之下&#xff0c;终于写完了这个无比拉跨的项目&#xff0c;最后一篇博客总体展示一下本项目运行效果兼测试&#xff0c;随后就是答辩被同学乱沙&#xff08;悲 刚打开软件&#xff0c;会看到如下欢迎界面&#xff0c;介绍本app的功能和优点 随后我们…

基于模型蒸馏的模型加速方案总结

1.简介 1.1目的 在过去的一段时间里&#xff0c;对基于模型蒸馏技术的模型加速方案的方法在多个数据集上进行了一系列的实验。所谓的模型蒸馏技术&#xff0c;简单的来说就是利用一个设计简单的小网络去学习一个设计比较复杂的大网络。特别的有&#xff0c;本次实验针对每一个…

串口通信例子SeriaPort

本篇例子使用的虚拟串口转自这位博主:http://t.csdnimg.cn/LSGIs 串口COM: 是一种用于联接计算机和外设设备的接口&#xff0c;也叫串行接口&#xff0c;简称com&#xff0c;常见的串口有一般电脑应用的RS-232(使用25帧或者9帧的连接器) 通俗来讲串口就是usb接口、鼠标窗口。键…

第二十四节:带你梳理Vue2 : Vue具名插槽/作用域插槽/v-slot指令

1. 具名插槽 1.1 没有使用具名插槽的问题 有的时候我们在使用子组件时,在子组件模板上不同的位置插入不同的内容, 只有一个插槽显然没法满足我们的需求,看示例: 需求如下: 子组件是一篇文章的结构父组件在调用子组件是给文章插入标题,正文,时间信息 示例代码如下: <di…

6.26.4.1 基于交叉视角变换的未配准医学图像多视角分析

1. 介绍 许多医学成像任务使用来自多个视图或模式的数据&#xff0c;但很难有效地将这些数据结合起来。虽然多模态图像通常可以在神经网络中作为多个输入通道进行配准和处理&#xff0c;但来自不同视图的图像可能难以正确配准(例如&#xff0c;[2])。因此&#xff0c;大多数多视…

创新实训博客(十三)——admin前端工作效果

管理/教师端前端工作汇总education-admin&#xff1a; 首先是登录注册页面的展示 管理员 首页 管理员登录后的首页如下图所示 管理员拥有所有的权限 课程管理 1、可以查看、修改、增添、删除课程列表内容 2、可以对课程资源进行操作 3、可以对课程的类别信息进行管理&…

一个最简单的MySQL事务模拟测试

这里只是简单写了一个转账的小事务&#xff0c;模拟一下事务的过程 代码&#xff1a; 初始数据&#xff1a; 当你关闭自动提交 并且开启一个事务执行了下面的更新语句 但是没有提交时&#xff1a; 此时虽然你运行查询语句会发现他的值发生了变化 &#xff0c;但是当你运行回滚…

51单片机看门狗定时器配置

测试环境 单片机型号&#xff1a;STC8G1K08-38I-TSSOP20&#xff0c;其他型号请自行测试&#xff1b; IDE&#xff1a;KEIL C51&#xff1b; 寄存器配置及主要代码 手册中关于看门狗的寄存器描述如下&#xff1a; 启动看门狗&#xff0c;需将B5位EN_WDT置1即可&#xff0c;…

大数据------额外软件、插件及技术------Linux(完整知识点汇总)

Linxu 不同领域的主流操作系统 桌面操作系统 WindowsMAac OSLinux 服务器端操作系统 UNIX&#xff08;付费&#xff09;LinuxWindows Server&#xff08;付费&#xff09; 移动设备操作系统 Android&#xff08;基于Linux开源&#xff09;IOS&#xff08;不开源&#xff09; 嵌…

时间序列分析入门:概念、模型与应用【ARMA、ARIMA模型】

在这篇博客中&#xff0c;我们将全面探讨时间序列分析的基本概念和分类&#xff0c;深入理解平稳性及其检验方法&#xff0c;并介绍自回归模型&#xff08;AR&#xff09;、滑动平均模型&#xff08;MA&#xff09;、自回归滑动平均模型&#xff08;ARMA&#xff09;以及自回归…