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

news2024/9/19 10:55:50

【设计模式-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,方便快捷,适合大多数场景。

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

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

相关文章

策略模式和状态模式

策略模式 在上下文中携带策略接口作为成员变量&#xff0c;在使用上下文之前需要设置策略setStrategy&#xff08;&#xff09;&#xff0c;然后使用策略接口成员变量来进行策略的执行。 步骤1&#xff1a;定义策略接口 // 策略接口 public interface Strategy {int execut…

面试突击:ArrayList源码详解

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。ArrayList 是我们日常开发中不可避免要使用到的一个类&#xff0c;并且在面试过程中也是一个非常高频的知识点&#…

酷睿Ultra 200V系CPU全阵容规格、跑分出炉:拉了坨大的

从最近几个月 12 代酷睿 CPU 大面积降价清库存&#xff0c;到 13、14 代高端 U 大范围翻车问题迟迟得不到解决。 这就很难不让人生出一种 Intel 似乎真无暇顾及老款 U&#xff0c;而是将有限精力通通放在了接下来酷睿 Ultra 处理器上的感觉。 当然&#xff0c;作为新工艺、新架…

【编译原理必考大题】 推导构建语法树,写出语法树的短语,简单短语和句柄

写在最前 本文为编译原理重点考察大题之一&#xff0c;理论基础见专栏文章&#xff0c;0基础直接使用也可食用 文章目录 推导构造语法树1.语法树的概念2. 子树&#xff0c;短语&#xff0c;简单短语&#xff0c;句柄2.1 子树2.2 短语2.3 简单短语与句柄2.4 真题实战 推导构造语…

Discourse OpenAI 生成图片

正如一些讨论的&#xff0c;生成图片是比较贵的。 差不多到了 1 元 一张图了。 就 OpenAI 生成了上面 4 张图&#xff0c;费用 0.4 美元。 Discourse OpenAI 生成图片 - Discourse - iSharkFly

AI 开发平台(Coze)搭建《AI女友(多功能版本)》

前言 本文讲解如何从零开始&#xff0c;使用扣子平台去搭建《AI女友&#xff08;多功能版本&#xff09;》 bot直达&#xff1a;AI女友&#xff08;多功能版&#xff09; - 扣子 AI Bot (coze.cn) 欢迎大家前去体验&#xff01;&#xff01;&#xff01; 正文 功能介绍 …

分别使用netty和apache.plc4x测试读取modbus协议的设备信号

记录一下常见的工业协议数据读取方法 目录 前言Modbus协议说明Netty 读取测试使用plc4x 读取测试结束语 前言 Modbus 是一种通讯协议&#xff0c;用于在工业控制系统中进行数据通信和控制。Modbus 协议主要分为两种常用的变体&#xff1a;Modbus RTU 和 Modbus TCP/IP Modbus …

平面点云格网过程及可视化介绍(python)

1、背景介绍 实际人工构造物中&#xff0c;很多物体表面为平面结构&#xff0c;因此将点云投影在二维平面上进行处理&#xff0c;如进行点云面积计算、点云边缘提取等。 具体案例可以参考博客&#xff1a;详解基于格网法统计平面点云面积_点云格网法计算xy投影面积-CSDN博客、点…

分页处理封装+分页查询题目列表

文章目录 1.sun-club-common封装分页1.com/sunxiansheng/subject/common/eneity/PageInfo.java2.com/sunxiansheng/subject/common/eneity/PageResult.java 2.sun-club-application-controller1.SubjectInfoDTO.java 继承PageInfo并新增字段2.SubjectController.java 3.sun-clu…

8个Unity开发高手都在用的秘密技巧!

1. 不要重新发明轮子&#xff0c;使用内置的引擎工具 在使用任何引擎时&#xff0c;比如Unity或Unreal Engine&#xff0c;一些开发者&#xff0c;主要是来自计算机科学领域的开发者&#xff0c;可能会倾向于从头开始开发大型算法或结构&#xff0c;而不去了解引擎中是否已经存…

三角洲行动卡顿严重?这样快速解决三角洲行动国服卡顿问题

三角洲行动官方精心设计的游戏地图和敌人布局&#xff0c;加上“曼德尔砖”等目标导向性道具的引入&#xff0c;更是为玩家之间的竞技和争夺增添了无数的变数。每一次的争夺都如同是一场智慧与勇气的较量&#xff0c;让人热血沸腾&#xff0c;无法自拔。在这个战场上&#xff0…

免费可视化工具如何提升工作效率?

免费可视化工具能为我们的工作带来什么好处&#xff1f;在如今数据密集的工作环境中&#xff0c;如何高效地处理和展示数据成为了每个行业的重要任务。传统的工具如Excel虽然强大&#xff0c;但在处理复杂数据和创建高级图表时往往显得力不从心。而免费可视化工具的出现&#x…

Arduino - 光敏传感器

Arduino - Light Sensor Arduino - 光传感器 In this tutorial, we are going to learn: 在本教程中&#xff0c;我们将学习&#xff1a; How light sensor works 光传感器的工作原理How to connect the light sensor to Arduino 如何将光传感器连接到ArduinoHow to progra…

C#udpClient组播

一、0udpClient 控件&#xff1a; button&#xff08;打开&#xff0c;关闭&#xff0c;发送&#xff09;&#xff0c;textbox&#xff0c;richTextBox 打开UDP&#xff1a; UdpClient udp: namespace _01udpClient {public partial class Form1 : Form{public Form1(){Initi…

如何在Windows 11上设置默认麦克风和相机?这里有详细步骤

如果你的Windows 11计算机上连接了多个麦克风或网络摄像头&#xff0c;并且希望自动使用特定设备&#xff0c;而不必每次都在设置中乱动&#xff0c;则必须将首选设备设置为默认设备。我们将向你展示如何做到这一点。 如何在Windows 11上更改默认麦克风 有两种方法可以将麦克…

[游戏开发][UE5]引擎使用学习记录

C Log和蓝图Log C Log 方法 UE_Log(参数1&#xff0c;参数2&#xff0c;参数3) //举例: UE_LOG(LogTemp, Error, TEXT("Log Info: %s"),"Test Log"); 三个参数的作用 参数1&#xff1a;输出窗口归类使用&#xff0c;你写什么它就显示什么 参数2&#x…

网络安全入门必选:十款免费的抓包工具有哪些?

下面给大家推荐几款好用的免费的抓包工具软件&#xff0c;有需要的小伙伴们来了解一下。 1. Wireshark抓包分析工具 4.0.1 Wireshark是一款功能强大的网络协议分析器&#xff0c;可以实时检测和抓取网络通讯数据。它支持多种协议和媒体类型&#xff0c;并具备丰富的显示过滤…

从0-1搭建一个web项目(package.json)详解

本章分析package.json文件详解 本文主要对packge.json配置子文件详解 ObJack-Admin一款基于 Vue3.3、TypeScript、Vite3、Pinia、Element-Plus 开源的后台管理框架。在一定程度上节省您的开发效率。另外本项目还封装了一些常用组件、hooks、指令、动态路由、按钮级别权限控制等…

干货:ANR日志分析全面解析

ANR类型 出现ANR的一般有以下几种类型&#xff1a; 1:KeyDispatchTimeout&#xff08;常见&#xff09; input事件在5S内没有处理完成发生了ANR。 logcat日志关键字&#xff1a;Input event dispatching timed out 2:BroadcastTimeout 前台Broadcast&#xff1a;onReceiver在…

MYSQL 四、mysql进阶 5(InnoDB数据存储结构)

一、数据库的存储结构&#xff1a;页 索引结构给我们提供了高效的索引方式&#xff0c;不过索引信息以及数据记录都是保存在文件上的&#xff0c;确切说时存储在页结构中&#xff0c;另一方面&#xff0c;索引是在存储引擎中实现的&#xff0c;Mysql服务器上的存储引擎负责对表…