当前位置: 首页 > news >正文

C++ 设计模式——原型模式

原型模式

    • 原型模式
      • 主要组成部分
      • 原型模式的使用步骤
      • 原型模式的 UML 图
      • 原型模式 UML 图解析
      • 优点和缺点
      • 适用场景
      • 总结

原型模式

原型(Prototype)模式是一种创建型模式。原型模式通过(原型对象)克隆出对个一模一样的对象。实际上,该模式与其说是一种设计模式,不如说是一种创建对象的方法(对象克隆),尤其是创建给定类的对象(实例)过程很复杂(例如,要设置许多成员变量的值)时,适用这种设计模式就比较合适。

引入“原型”(Prototype)模式的定义:用原型实例指定创建对象的类型,并且通过复制这些原型创建新的对象。简单来说,就是通过克隆来创建新的对象实例。

主要组成部分

  • 原型接口 (Prototype Interface):定义一个克隆方法,通常是 clone(),用于复制当前对象的实例。
  • 具体原型类 (Concrete Prototype):实现原型接口,提供具体的克隆实现。每个具体原型类都可以被克隆以创建新对象。
  • 客户端 (Client):使用原型对象来创建新对象。客户端通过调用原型的克隆方法来获得新对象,而不是直接使用构造函数。

原型模式的使用步骤

  1. 定义原型接口

    创建一个包含克隆方法的抽象类 Monster

    //怪物父类
    class Monster
    {
    public://构造函数Monster(int life, int magic, int attack) :m_life(life), m_magic(magic), m_attack(attack) {}virtual ~Monster() {} //做父类时析构函数应该为虚函数public:virtual Monster* clone() = 0; //具体的实现在子类中进行protected: //可能被子类访问的成员,用protected修饰//怪物属性int m_life;    //生命值int m_magic;   //魔法值int m_attack;  //攻击力
    };
    
  2. 实现具体原型类

    创建具体的怪物类,继承自 Monster,并实现 clone() 方法。

    //亡灵类怪物
    class M_Undead :public Monster
    {
    public://构造函数M_Undead(int life, int magic, int attack) :Monster(life, magic, attack){cout << "一只亡灵类怪物来到了这个世界" << endl;}public://拷贝构造函数M_Undead(const M_Undead& tmpobj) :Monster(tmpobj){cout << "调用了M_Undead::M_Undead(const M_Undead& tmpobj)拷贝构造函数创建了一只亡灵类怪物" << endl;}virtual Monster* clone(){return new M_Undead(*this); //触发拷贝构造函数的调用来创建亡灵类怪物}//其他代码略....
    };//元素类怪物
    class M_Element :public Monster
    {
    public://构造函数M_Element(int life, int magic, int attack) :Monster(life, magic, attack){cout << "一只元素类怪物来到了这个世界" << endl;}public://拷贝构造函数M_Element(const M_Element& tmpobj) :Monster(tmpobj) //初始化列表中注意对父类子对象的初始化{cout << "调用了M_Element::M_Element(const M_Element& tmpobj)拷贝构造函数创建了一只元素类怪物" << endl;}virtual Monster* clone(){return new M_Element(*this);}//其他代码略....
    };//机械类怪物
    class M_Mechanic :public Monster
    {
    public://构造函数M_Mechanic(int life, int magic, int attack) :Monster(life, magic, attack){cout << "一只机械类怪物来到了这个世界" << endl;}public://拷贝构造函数M_Mechanic(const M_Mechanic& tmpobj) :Monster(tmpobj){cout << "调用了M_Mechanic::M_Mechanic(const M_Mechanic& tmpobj)拷贝构造函数创建了一只机械类怪物" << endl;}virtual Monster* clone(){return new M_Mechanic(*this);}//其他代码略....
    };
    
  3. 使用客户端

    在客户端代码中,创建原型对象并使用克隆方法生成新对象。

    int main()
    {// 创建原型对象Monster* undead = new M_Undead(100, 50, 20);Monster* element = new M_Element(80, 60, 25);Monster* mechanic = new M_Mechanic(120, 30, 30);// 克隆对象Monster* clonedUndead = undead->clone();Monster* clonedElement = element->clone();Monster* clonedMechanic = mechanic->clone();// 使用克隆对象...// 例如,可以在这里对克隆对象进行操作或输出属性// 清理内存delete undead;delete element;delete mechanic;delete clonedUndead;delete clonedElement;delete clonedMechanic;return 0;
    }
    

原型模式的 UML 图

原型模式的 UML 图

原型模式 UML 图解析

  • 类关系
    • Prototype(原型类):这是一个抽象类,定义了克隆接口(通常是 clone() 方法)。在 UML 图中,对应于 Monster 类。
    • ConcretePrototype(具体原型类):这些是实现了 Prototype 接口的具体类,负责实现克隆逻辑。图中的 M_UndeadM_ElementM_Mechanic 是具体原型类。
  • 稳定与变化
    • 稳定部分Prototype 类(如 Monster)通常保持不变,定义了基本的属性和克隆接口。
    • 变化部分ConcretePrototype 类(如 M_UndeadM_Element 等)是变化的部分,可以根据需求添加新的具体类。
  • 信息隐藏
    • 客户端代码与 Prototype 接口交互,而不需要了解具体的实现细节。这种设计实现了信息隐藏,使得系统更加灵活。
  • 扩展性
    • 新的具体原型类可以通过实现 Prototype 接口来扩展,而不需要修改现有的代码结构,符合开闭原则。

优点和缺点

优点

  • 简化对象创建:通过克隆现有对象,避免了复杂的构造过程,尤其是当对象需要大量初始化参数时。
  • 提高灵活性:客户端不需要了解具体的对象创建逻辑,只需使用原型进行克隆,增强了代码的灵活性和可维护性。
  • 支持动态配置:可以在运行时决定克隆哪种类型的对象,适应性强。

缺点

  • 性能开销:克隆对象可能导致较大的内存开销,特别是在对象较大或复杂时。
  • 深拷贝与浅拷贝:需要明确区分深拷贝和浅拷贝,错误的实现可能导致共享状态问题。
  • 增加复杂性:需要实现克隆方法,可能会增加代码的复杂性,特别是在有多个子类时。

适用场景

  • 对象创建过程复杂:当对象的构造过程非常复杂,涉及多个参数初始化时,使用原型模式可以简化这一过程。
  • 需要大量相似对象:当需要创建大量相似对象时,使用克隆原型可以提高效率。
  • 运行时动态创建:当对象类型在运行时动态决定时,原型模式可以提供灵活的解决方案。
  • 避免构造函数的重复调用:在需要频繁创建相似对象的场景中,原型模式可以避免重复调用构造函数,提高性能。

总结

原型模式通过定义 PrototypeConcretePrototype 的关系,使得对象的克隆过程更加灵活和高效。客户端只需依赖于 Prototype 接口,能够动态创建新的对象实例,增强了系统的可扩展性和可维护性。

相关文章:

C++ 设计模式——原型模式

原型模式 原型模式主要组成部分原型模式的使用步骤原型模式的 UML 图原型模式 UML 图解析优点和缺点适用场景总结 原型模式 原型(Prototype)模式是一种创建型模式。原型模式通过(原型对象)克隆出对个一模一样的对象。实际上&#xff0c;该模式与其说是一种设计模式&#xff0c…...

【Harmony OS 4.0】待办列表案例

src/main/ets/example1/Models.ets // 定义class类数据模型 export class TaskDataModel {// private 私有属性&#xff0c;在类对象外不允许随意更改数据&#xff0c;必须本地初始化。private tasks: Array<string> [早起晨练, 准备早餐, 阅读名著, 学习ArkTs, 玩游戏…...

快速把文件名统计到excel表的方法

文件名统计到EXCEL表&#xff0c;这似乎很多人都没听说过&#xff0c;因为它与EXCEL表格不沾边&#xff0c;那么这个需求如何实现&#xff0c;用到什么方法&#xff0c;今天给大家介绍一个比较实用的方法&#xff0c;它可以把文件名或文件夹的名快速提取并统计到EXCEL表格上去。…...

开源通用验证码识别OCR —— DdddOcr 源码赏析(一)

文章目录 [toc] 前言DdddOcr环境准备安装DdddOcr使用示例 源码分析实例化DdddOcr实例化过程 分类识别分类识别过程 未完待续 前言 DdddOcr 源码赏析 DdddOcr DdddOcr是开源的通用验证码识别OCR 官方传送门 环境准备 安装DdddOcr pip install ddddocr使用示例 示例图片如…...

上升ECMAScript性能优化技巧与陷阱(下)

4. 深拷贝和浅拷贝的选择不当 在JavaScript中&#xff0c;对象是通过引用传递的&#xff0c;这意味着当你将一个对象赋值给另一个变量时&#xff0c;你实际上是在传递对象的引用&#xff0c;而不是对象本身。这导致了一个常见的问题&#xff1a;当你修改一个对象的属性时&…...

用7EPhone云手机进行TikTok的矩阵运营

“根据市局机构Statista发布的报告显示&#xff0c;截至2024年4月&#xff0c;TikTok全球下载量超过49.2亿次&#xff0c;月度活跃用户数超过15.82亿。TikTok的流量受欢迎程度可想而知&#xff0c;也一跃成为了全球第五大最受欢迎的社交APP。” 人群密集的地方社区也是适合推广…...

谷歌浏览器下载文件被阻止怎么解除

在工作生活中&#xff0c;我们会使用谷歌浏览器下载各种各样的文件&#xff0c;不过偶尔会遇到文件下载被阻止的情况。为了解决这一问题&#xff0c;本文为大家分享了实用的措施建议&#xff0c;一起来了解一下吧。&#xff08;本文由https://chrome.cmrrs.com/站点的作者进行编…...

apt E: 无法定位软件包 winehq-stable

执行了 添加wine源 wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources还需要执行 更新源 apt update...

P2460[SDOI2007] 科比的比赛

第一次做洛谷系列&#xff0c;紧张&#xff0c;请多关照哦 题目传送门&#xff1a;[SDOI2007] 科比的比赛 - 洛谷 思路分析 这道题大概题意是给定我们的主人公 Kobe Bryant 的 mm 个对手&#xff0c;nn 场比赛相对应的获胜概率。求 Kobe Bryant 最大全部获胜概率和打败对手能…...

linux学习--第二天

--Linux文件系统 -显示文件命令 cat 1. cat -b 文件&#xff1a;从1开始对非空输出行编号 2. cat -n 文件&#xff1a;从1开始对所有行编号 3. cat -s 文件&#xff1a;将连续多行空白行合并 more&#xff08;显示一屏文本内容&#xff09; 1. more -num 文件&#xff…...

使用 Flask、Celery 和 Python 实现每月定时任务

为了创建一个使用 Flask、Celery 和 Python 实现的每月定时任务&#xff0c;我们需要按照以下步骤进行&#xff1a; 1.安装必要的库 我们需要安装 Flask、Celery 和 Redis&#xff08;作为消息代理&#xff09;。我们可以使用 pip 来安装它们&#xff1a; bash复制代码 ​ p…...

【c语言】整数在内存中的储存(大小端字节序)

整数在内存中的储存&#xff08;大小端字节序&#xff09; 1.整数在内存中的储存 2.大小端字节序 3.整数在内存中储存例子 4.字节序判断 5.死循环现象 文章目录 整数在内存中的储存&#xff08;大小端字节序&#xff09;整数在内存中的储存大小端字节序什么是大小端为什么会有…...

浅谈SIMD、向量化处理及其在StarRocks中的应用

前言 单指令流多数据流(SIMD)及其衍生出来的向量化处理技术已经有了相当的历史&#xff0c;并且也是高性能数据库、计算引擎、多媒体库等组件的标配利器。笔者在两年多前曾经做过一次有关该主题的内部Geek分享&#xff0c;但可能是由于这个topic离实际研发场景比较远&#xff0…...

【ML】Image Augmentation)的作用、使用方法及其分类

图像增强&#xff08;Image Augmentation&#xff09;的作用、使用方法及其分类 1. 图像增强的定义2. 图像增强的作用3. 什么时候使用图像增强&#xff1f;4. 图像增强详细方法分类梳理4.1 图像增强方法列表4.2 边界框增强方法5. 参考资料 yolov3&#xff08;一&#xff1a;模型…...

设计模式六大原则(一)--单一职责原则

1. 简介 1.1. 概述 一个类或模块应该只负责完成一项任务或承担一个责任。如果一个类或模块承担了多个职责,那么当需要修改其中一个职责的功能时,就可能会对其他职责产生影响,从而导致代码耦合度增加,维护起来更加困难。 1.2. 主要特点 单一职责原则(Single Responsibi…...

c语言学习,malloc()函数分析

1&#xff1a;malloc() 函数说明&#xff1a; 申请配置size大小内存空间 2&#xff1a;函数原型&#xff1a; void *malloc(size_t size) 3&#xff1a;函数参数&#xff1a; 参数size&#xff0c;为申请内存大小 4&#xff1a;返回值&#xff1a; 配置成功则返回指针&#…...

【运维项目经历|041】上云项目-物理机迁移到阿里云

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 ​ 🏅阿里云ACE认证高级工程师 ​ 🏅阿里云开发者社区专家博主 💊交流社区:CSDN云计算交流社区欢迎您的加入! 目录 项目名称 项目背景 项目目标 项…...

分组并合并其它列的非空值 --Excel难题#83

Excel第1列是分类&#xff0c;第2-42列是平行的多个数据项列&#xff0c;下表用部分列示例。数据有X或null两种情况&#xff0c;同一个分类的同一列数据偶尔有重复。 ABCDE1IDCriteria1Criteria2Criteria3Criteria42FirstValueX3FirstValueX4FirstValueX5FirstValueX6SecondVa…...

VM相关配置及docker

NAT——VMnet8网卡 桥接——WLAN/网线 仅主机——VMnet1网卡 docker与虚拟机的区别 启动docker服务 systemctl start docker 重启 systemctl start docker关闭docker服务 systemctl stop docker.servicedocker的两大概念 镜像&#xff1a;images&#xff0c;应用程序的静态文…...

Redis中Set数据类型常用命令

目录 1. 添加元素 2. 移除元素 3. 检查成员是否存在 4. 获取集合成员 5. 获取集合成员数量 6. 随机获取集合中的一个成员 7. 集合运算 8. 集合的移值 9. 提供集合的随机元素 在Redis中&#xff0c;Set是一种无序且不重复的字符串集合。 1. 添加元素 SADD key member [member ..…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...