技术成神之路:设计模式(三)原型模式

news2025/1/2 0:26:23

1. 定义


原型模式(Prototype Pattern)是一种创建型设计模式,旨在通过复制现有对象来创建新对象,而不是通过实例化类的方式。这个模式可以提高对象创建的效率,尤其是在创建对象的过程非常复杂或代价高昂时。

2. 结构


原型模式包含以下角色:

  • Prototype(原型接口):用于声明克隆自身的方法。通常这个接口会定义一个名为clone的抽象方法。
  • ConcretePrototype(具体原型类):实现原型接口,并实现克隆自身的方法。这类对象可以被克隆。
  • Client(客户端):使用原型接口来克隆新的对象。

UML类图:
在这里插入图片描述

3. 示例代码


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

// 具体原型类A
class ConcretePrototypeA implements Prototype {
    private String name;

    public ConcretePrototypeA(String name) {
        this.name = name;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototypeA{name='" + name + "'} hashcode= "+ hashCode();
    }
}

// 具体原型类B
class ConcretePrototypeB implements Prototype {
    private int value;

    public ConcretePrototypeB(int value) {
        this.value = value;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototypeB{value=" + value + "} hashcode= "+ hashCode();
    }
}

测试:

@Test
    public void test() {
        ConcretePrototypeA prototypeA = new ConcretePrototypeA("Prototype A");
        ConcretePrototypeB prototypeB = new ConcretePrototypeB(42);

        Prototype clonedPrototypeA = prototypeA.clone();
        Prototype clonedPrototypeB = prototypeB.clone();

        System.out.println("原型A: "+prototypeA);
        System.out.println("克隆A: "+clonedPrototypeA);
        System.out.println("原型B: "+prototypeB);
        System.out.println("克隆B: "+clonedPrototypeB);
    }

打印:

原型A: ConcretePrototypeA{name='Prototype A'} hashcode= 1823541245
克隆A: ConcretePrototypeA{name='Prototype A'} hashcode= 1020154737
原型B: ConcretePrototypeB{value=42} hashcode= 398457879
克隆B: ConcretePrototypeB{value=42} hashcode= 1850954068

4. 应用场景


  • 对象的创建开销很大:通过克隆现有对象而不是重新创建,可以节省时间和资源。
  • 系统需要大量类似对象:通过克隆原型对象,可以快速生成多个相似但独立的对象。
  • 对象的状态需要动态改变:通过克隆原型对象,可以创建具有特定状态的新对象。

情景回顾:

原型模式在实际应用中可能并不常见,或许你见到过但没留意,因为它的应用场景太少了,让我想起了在写一个多任务下载模块时,每下载一个文件其都有对应的mode,记录一些下载信息状态信息等内容,再进行更新进度的时候需要把这个对象发送出去,通知外界更新UI,有一个问题就是下载中操作的对象和发送出去的对象是同一个,就会出现异常现象,我发送出去的下载进度是90%,UI还没来得及更新,这边又将进度修改为95%了,emm… 可能我描述的问题,你觉的不严重,但这种不可预测的现象是我们不希望发生的。
其中解决方式一 就是克隆一个对象,让UI显示的和下载操作的对象互不干扰,这时如果你new一个新对象的话相比克隆就劣势就凸显出来了。

5. 优缺点


优点:

  • 提高对象创建效率:避免了复杂对象的重复创建,通过克隆现有对象来生成新对象。
  • 动态创建对象:可以在运行时动态创建对象,而无需了解具体的类。
  • 减少子类的数量:通过克隆原型对象,可以减少创建子类的数量,增强系统的灵活性。

缺点:

  • 深拷贝和浅拷贝问题:在涉及复杂对象时,深拷贝和浅拷贝的问题需要特别注意。如果对象包含对其他对象的引用,浅拷贝可能不够用,需要实现深拷贝。
  • 克隆方法的实现复杂:对于一些复杂的对象,克隆方法的实现可能比较复杂,需要处理对象间的依赖关系。

6. 深拷贝与浅拷贝


在原型模式中,克隆可以分为浅拷贝和深拷贝:

  • 浅拷贝:复制对象时,只复制对象本身,而不复制对象所引用的其他对象。也就是说,复制后的对象与原对象共享对其他对象的引用。
  • 深拷贝:复制对象时,不仅复制对象本身,还复制对象所引用的其他对象。这样,复制后的对象与原对象是完全独立的,不共享任何引用。

7. 深拷贝与浅拷贝示例


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

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

    public ConcretePrototype(String name) {
        this.name = name;
        this.list = new ArrayList<>();
    }

    public void addToList(String item) {
        list.add(item);
    }

    public List<String> getList() {
        return list;
    }

    @Override
    public Prototype clone() {
        try {
            ConcretePrototype copy = (ConcretePrototype) super.clone();
            // 深拷贝 -测试浅拷贝时注释下面代码!!!
            copy.list = new ArrayList<>(this.list);
            return copy;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototype{name='" + name + "', list=" + list + "} list hashcode=" + list.hashCode();
    }
}

测试:

    @Test
    public void test() {
        ConcretePrototype prototype = new ConcretePrototype("Prototype");
        prototype.addToList("Item1");
        prototype.addToList("Item2");

        // 浅拷贝示例
        ConcretePrototype shallowClone = (ConcretePrototype) prototype.clone();

        // 添加新项到原型对象的列表
        prototype.addToList("Item3");

        System.out.println("原型: " + prototype);
        System.out.println("浅拷贝: " + shallowClone);

        // 深拷贝示例
        ConcretePrototype deepClone = (ConcretePrototype) prototype.clone();

        // 添加新项到深拷贝对象的列表
        deepClone.addToList("Item4");

        System.out.println("原型: " + prototype);
        System.out.println("深拷贝: " + deepClone);
    }

测试浅拷贝打印:

原型: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142
浅拷贝: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142

可以看出两个对象所引用的list对象为同一个

测试深拷贝打印:

原型: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3]} list hashcode=1757018142
深拷贝: ConcretePrototype{name='Prototype', list=[Item1, Item2, Item3, Item4]} list hashcode=-1296039165

两个对象引用的list完全不一样了,操作互不影响

8. 设计模式的比较


原型模式与其他创建型设计模式(如工厂模式、抽象工厂模式、单例模式等)有其独特之处:

  • 与工厂模式的区别:工厂模式通过提供一个方法来创建对象,而原型模式通过复制现有对象来创建新的对象。工厂模式适合对象创建过程简单但需要解耦对象创建过程的场景,而原型模式适合对象创建过程复杂且需要高效创建对象的场景。
  • 与单例模式的区别:单例模式确保一个类只有一个实例,而原型模式则允许通过克隆来创建多个实例。它们解决的问题不同,前者关注的是实例的唯一性,后者关注的是高效创建对象。

9. 结论


原型模式是一种高效的对象创建模式,它通过克隆现有对象来创建新对象,避免了通过构造函数创建对象的高昂代价,尽管原型模式在许多方面具有优势,但在实现过程中需要注意对象间的引用关系,确保深拷贝和浅拷贝的正确实现,以避免不必要的资源浪费和潜在的错误。

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

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

相关文章

三分钟看懂SMD封装与COB封装的差异

全彩LED显示屏领域中&#xff0c;COB封装于SMD封装是比较常见的两种封装方式&#xff0c;SMD封装产品主要有常规小间距以及室内、户外型产品&#xff0c;COB封装产品主要集中在小间距以及微间距系列产品中&#xff0c;今天跟随COB显示屏厂家中品瑞一起快速看懂SMD封装与COB封装…

Let‘s Encrypt 申请免费 SSL 证书(60天以后自动更新证书)

文章目录 官网文档简介安装 Nginxacme.sh生成证书智能化生成证书 安装证书查看已安装证书更新证书 官网 https://letsencrypt.org/zh-cn/ 文档 https://letsencrypt.org/zh-cn/docs/ 简介 Let’s Encrypt 是一个非营利组织提供的免费SSL/TLS证书颁发机构&#xff0c;旨在促…

滚珠花键促进汽车产业整体升级与发展!

滚珠花键能够实现高效的传动和连接&#xff0c;确保物体在运动过程中的精确位置和稳定性&#xff0c;被广泛应用于机械制造、航空航天、工业自动化、工业汽车、工业机器人、高速铁路等领域。为各个行业的发展提供了重要支持&#xff0c;尤其是在工业汽车领域中&#xff0c;为我…

Spring系统学习-什么是AOP?为啥使用AOP?

问题思考 我们为啥要使用AOP? 来看一个案例&#xff1a; 声明计算器接口Calculator&#xff0c;包含加减乘除的抽象方法 public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j); }public class Calculat…

HNU电子测试平台与工具2_《计算机串口使用与测量》

&#xff08;这个有留word哈哈&#xff09; 4.1 4.2 Linux 操作系统平台 一、实验目的 了解 Linux 系统文件系统的基本组织了解 Linux 基本的多用户权限系统熟练使用 ls、cd、cat、more、sudo、gcc、vim 等基本命令会使用 ls 和 chmod 命令查看和修改文件权限 二、实…

使用机器学习,通过文本分析,轻松实现原本复杂的情感分析

01、案例说明 本期分享案例是&#xff1a;文字分析-情感分析&#xff0c;内容是关于某部电影评论好坏的分析&#xff0c;使用大量的已知数据&#xff0c;通过监督学习的方法&#xff0c;可以对于未知的评论进行判断其为正面还是负面的评价。 对于数据分析&#xff0c;原来都是…

contrastive loss and triplet loss

contrastive loss 想要positive pair 的距离接近0 而triplet loss只需要postive pair的距离 和 negtaive pair 的距离相差m以上, postive pair的距离不一定为0, 所以条件更松驰, 为网络训练更友好一点 reference: https://www.youtube.com/watch?vBcF6FfZHDqA

图书管理系统(含登录验证码操作)

文章目录 登录需求分析登录界面注册功能&#xff1a;登录功能&#xff1a;忘记密码&#xff1a;验证码规则&#xff1a; 图书管理系统需求Book包Book类BookList类 IOperation包IOperation接口查找图书新增图书删除图书显示图书借阅图书归还图书退出系统 User包user类Users类adm…

【Java】如果让你设计一个分布式链路跟踪系统?你怎么做?

一、问题解析 分布式链路跟踪服务属于写多读少的服务&#xff0c;是我们线上排查问题的重要支撑。我经历过的一个系统&#xff0c;同时支持着多条业务线&#xff0c;实际用上的服务器有两百台左右&#xff0c;这种量级的系统想排查故障&#xff0c;难度可想而知。 因此&#…

大数据------JavaWeb------JSP(完整知识点汇总)

JSP 定义 JSP&#xff08;Java Server Pages&#xff09;&#xff0c;即Java服务端页面。它是一种动态的网页技术&#xff0c;其中可以定义HTML、CSS、JS等静态内容&#xff0c;还可以定义Java代码的动态内容JSP HTML Java 说白了JSP就是一个页面&#xff0c;它既可以写HTML标…

昇思第8天

保存与加载 保存模型使用save_checkpoint接口&#xff0c;传入网络和指定的保存路径 要加载模型权重&#xff0c;需要先创建相同模型的实例&#xff0c;然后使用load_checkpoint和load_param_into_net方法加载参数。 使用静态图加速 AI编译框架分为两种运行模式&#xff0c…

红酒与建筑:品味历史与艺术的交汇

在时间的长河中&#xff0c;红酒与建筑都是人类智慧的结晶&#xff0c;它们各自承载着历史的厚重与艺术的韵味。当这两者交汇时&#xff0c;仿佛是一场穿越时空的对话&#xff0c;将我们带入一个既古老又现代、既深沉又温柔的世界。今天&#xff0c;就让我们一起走进这个奇妙的…

鸿翼FEX文件安全交换系统,打造安全高效的文件摆渡“绿色通道”

随着数字经济时代的到来&#xff0c;数据已成为最有价值的生产要素&#xff0c;是企业的重要资产之一。随着数据流动性的增强&#xff0c;数据安全问题也随之突显。尤其是政务、金融、医疗和制造业等关键领域组织和中大型企业&#xff0c;面临着如何在保障数据安全的同时&#…

Windows11 安装MySQL

MySQL下载官网 安装教程参考 选择Windows离线安装 典型安装

springboot大学生请假管理系统-计算机毕业设计源码17453

摘 要 从20年代开始&#xff0c;计算机疯狂的出现在人们的生活以及工作当中&#xff0c;成为人们生活、工作的好帮手&#xff0c;计算机深入到每家每户当中&#xff0c;网络办公&#xff0c;网络教学更是替换了传统手工记录管理的方式&#xff0c;使用计算机办公可以不必局限于…

3D模型如何在力控组态中打开?---模大狮模型网

在展览3D模型设计行业中&#xff0c;力控组态是一个关键的技术应用。通过适当的力控组态&#xff0c;可以实现模型的互动性和真实感&#xff0c;提升展览效果和用户体验。本文将探讨如何在力控组态中打开和应用3D模型&#xff0c;从而达到更加生动和引人入胜的展示效果。 一、了…

Linux文件与日志

目录 1. Linux 文件系统 1.1 inode号 1.2 EXT类型文件恢复 1.3 xfs类型文件备份和恢复 2. 日志分析 2.1 日志类型 2.2日志配置文件 2.3 日志分析的重要性 在Linux系统中&#xff0c;文件和日志是管理和维护系统运行所不可或缺的。理解它们的工作原理和如何有效地管理和…

民宿小程序开发,在线预订模式

一、开发背景 如今&#xff0c;随着互联网技术的快速发展&#xff0c;大众的生活消费都集中在了手机上&#xff0c;通过手机进行各种活动&#xff0c;同时也包括了预订酒店民宿&#xff0c;由此&#xff0c;民宿预约小程序出现在了大众的生活中。 二、民宿小程序特点 民宿小…

the problem when using langchain chat openai model and crewai same llm models

题意&#xff1a; when i am using langchain chat openai model and invoking method its working but when using in crewai same llm models it gives invalid api key 当你提到在使用 langchain 的 chatopenai 模型并调用方法时一切正常&#xff0c;但在 crewai 中使用相…

MySql Innodb 索引有哪些与详解

概述 对于MYSQL的INNODB存储引擎的索引&#xff0c;大家是不陌生的&#xff0c;都能想到是 B树结构&#xff0c;可以加速SQL查询。但对于B树索引&#xff0c;它到底“长”得什么样子&#xff0c;它具体如何由一个个字节构成的&#xff0c;这些的基础知识鲜有人深究。本篇文章从…