C++ 设计模式——原型模式
原型模式
- 原型模式
- 主要组成部分
- 原型模式的使用步骤
- 原型模式的 UML 图
- 原型模式 UML 图解析
- 优点和缺点
- 适用场景
- 总结
原型模式
原型(Prototype)模式是一种创建型模式。原型模式通过(原型对象)克隆出对个一模一样的对象。实际上,该模式与其说是一种设计模式,不如说是一种创建对象的方法(对象克隆),尤其是创建给定类的对象(实例)过程很复杂(例如,要设置许多成员变量的值)时,适用这种设计模式就比较合适。
引入“原型”(Prototype)模式的定义:用原型实例指定创建对象的类型,并且通过复制这些原型创建新的对象。简单来说,就是通过克隆来创建新的对象实例。
主要组成部分
- 原型接口 (Prototype Interface):定义一个克隆方法,通常是
clone(),用于复制当前对象的实例。 - 具体原型类 (Concrete Prototype):实现原型接口,提供具体的克隆实现。每个具体原型类都可以被克隆以创建新对象。
- 客户端 (Client):使用原型对象来创建新对象。客户端通过调用原型的克隆方法来获得新对象,而不是直接使用构造函数。
原型模式的使用步骤
-
定义原型接口
创建一个包含克隆方法的抽象类
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; //攻击力 }; -
实现具体原型类
创建具体的怪物类,继承自
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);}//其他代码略.... }; -
使用客户端
在客户端代码中,创建原型对象并使用克隆方法生成新对象。
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 图解析
- 类关系:
- Prototype(原型类):这是一个抽象类,定义了克隆接口(通常是
clone()方法)。在 UML 图中,对应于Monster类。 - ConcretePrototype(具体原型类):这些是实现了 Prototype 接口的具体类,负责实现克隆逻辑。图中的
M_Undead、M_Element和M_Mechanic是具体原型类。
- Prototype(原型类):这是一个抽象类,定义了克隆接口(通常是
- 稳定与变化:
- 稳定部分:Prototype 类(如
Monster)通常保持不变,定义了基本的属性和克隆接口。 - 变化部分:ConcretePrototype 类(如
M_Undead、M_Element等)是变化的部分,可以根据需求添加新的具体类。
- 稳定部分:Prototype 类(如
- 信息隐藏:
- 客户端代码与 Prototype 接口交互,而不需要了解具体的实现细节。这种设计实现了信息隐藏,使得系统更加灵活。
- 扩展性:
- 新的具体原型类可以通过实现 Prototype 接口来扩展,而不需要修改现有的代码结构,符合开闭原则。
优点和缺点
优点:
- 简化对象创建:通过克隆现有对象,避免了复杂的构造过程,尤其是当对象需要大量初始化参数时。
- 提高灵活性:客户端不需要了解具体的对象创建逻辑,只需使用原型进行克隆,增强了代码的灵活性和可维护性。
- 支持动态配置:可以在运行时决定克隆哪种类型的对象,适应性强。
缺点:
- 性能开销:克隆对象可能导致较大的内存开销,特别是在对象较大或复杂时。
- 深拷贝与浅拷贝:需要明确区分深拷贝和浅拷贝,错误的实现可能导致共享状态问题。
- 增加复杂性:需要实现克隆方法,可能会增加代码的复杂性,特别是在有多个子类时。
适用场景
- 对象创建过程复杂:当对象的构造过程非常复杂,涉及多个参数初始化时,使用原型模式可以简化这一过程。
- 需要大量相似对象:当需要创建大量相似对象时,使用克隆原型可以提高效率。
- 运行时动态创建:当对象类型在运行时动态决定时,原型模式可以提供灵活的解决方案。
- 避免构造函数的重复调用:在需要频繁创建相似对象的场景中,原型模式可以避免重复调用构造函数,提高性能。
总结
原型模式通过定义 Prototype 和 ConcretePrototype 的关系,使得对象的克隆过程更加灵活和高效。客户端只需依赖于 Prototype 接口,能够动态创建新的对象实例,增强了系统的可扩展性和可维护性。
相关文章:
C++ 设计模式——原型模式
原型模式 原型模式主要组成部分原型模式的使用步骤原型模式的 UML 图原型模式 UML 图解析优点和缺点适用场景总结 原型模式 原型(Prototype)模式是一种创建型模式。原型模式通过(原型对象)克隆出对个一模一样的对象。实际上,该模式与其说是一种设计模式,…...
【Harmony OS 4.0】待办列表案例
src/main/ets/example1/Models.ets // 定义class类数据模型 export class TaskDataModel {// private 私有属性,在类对象外不允许随意更改数据,必须本地初始化。private tasks: Array<string> [早起晨练, 准备早餐, 阅读名著, 学习ArkTs, 玩游戏…...
快速把文件名统计到excel表的方法
文件名统计到EXCEL表,这似乎很多人都没听说过,因为它与EXCEL表格不沾边,那么这个需求如何实现,用到什么方法,今天给大家介绍一个比较实用的方法,它可以把文件名或文件夹的名快速提取并统计到EXCEL表格上去。…...
开源通用验证码识别OCR —— DdddOcr 源码赏析(一)
文章目录 [toc] 前言DdddOcr环境准备安装DdddOcr使用示例 源码分析实例化DdddOcr实例化过程 分类识别分类识别过程 未完待续 前言 DdddOcr 源码赏析 DdddOcr DdddOcr是开源的通用验证码识别OCR 官方传送门 环境准备 安装DdddOcr pip install ddddocr使用示例 示例图片如…...
上升ECMAScript性能优化技巧与陷阱(下)
4. 深拷贝和浅拷贝的选择不当 在JavaScript中,对象是通过引用传递的,这意味着当你将一个对象赋值给另一个变量时,你实际上是在传递对象的引用,而不是对象本身。这导致了一个常见的问题:当你修改一个对象的属性时&…...
用7EPhone云手机进行TikTok的矩阵运营
“根据市局机构Statista发布的报告显示,截至2024年4月,TikTok全球下载量超过49.2亿次,月度活跃用户数超过15.82亿。TikTok的流量受欢迎程度可想而知,也一跃成为了全球第五大最受欢迎的社交APP。” 人群密集的地方社区也是适合推广…...
谷歌浏览器下载文件被阻止怎么解除
在工作生活中,我们会使用谷歌浏览器下载各种各样的文件,不过偶尔会遇到文件下载被阻止的情况。为了解决这一问题,本文为大家分享了实用的措施建议,一起来了解一下吧。(本文由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] 科比的比赛
第一次做洛谷系列,紧张,请多关照哦 题目传送门:[SDOI2007] 科比的比赛 - 洛谷 思路分析 这道题大概题意是给定我们的主人公 Kobe Bryant 的 mm 个对手,nn 场比赛相对应的获胜概率。求 Kobe Bryant 最大全部获胜概率和打败对手能…...
linux学习--第二天
--Linux文件系统 -显示文件命令 cat 1. cat -b 文件:从1开始对非空输出行编号 2. cat -n 文件:从1开始对所有行编号 3. cat -s 文件:将连续多行空白行合并 more(显示一屏文本内容) 1. more -num 文件ÿ…...
使用 Flask、Celery 和 Python 实现每月定时任务
为了创建一个使用 Flask、Celery 和 Python 实现的每月定时任务,我们需要按照以下步骤进行: 1.安装必要的库 我们需要安装 Flask、Celery 和 Redis(作为消息代理)。我们可以使用 pip 来安装它们: bash复制代码 p…...
【c语言】整数在内存中的储存(大小端字节序)
整数在内存中的储存(大小端字节序) 1.整数在内存中的储存 2.大小端字节序 3.整数在内存中储存例子 4.字节序判断 5.死循环现象 文章目录 整数在内存中的储存(大小端字节序)整数在内存中的储存大小端字节序什么是大小端为什么会有…...
浅谈SIMD、向量化处理及其在StarRocks中的应用
前言 单指令流多数据流(SIMD)及其衍生出来的向量化处理技术已经有了相当的历史,并且也是高性能数据库、计算引擎、多媒体库等组件的标配利器。笔者在两年多前曾经做过一次有关该主题的内部Geek分享,但可能是由于这个topic离实际研发场景比较远࿰…...
【ML】Image Augmentation)的作用、使用方法及其分类
图像增强(Image Augmentation)的作用、使用方法及其分类 1. 图像增强的定义2. 图像增强的作用3. 什么时候使用图像增强?4. 图像增强详细方法分类梳理4.1 图像增强方法列表4.2 边界框增强方法5. 参考资料 yolov3(一:模型…...
设计模式六大原则(一)--单一职责原则
1. 简介 1.1. 概述 一个类或模块应该只负责完成一项任务或承担一个责任。如果一个类或模块承担了多个职责,那么当需要修改其中一个职责的功能时,就可能会对其他职责产生影响,从而导致代码耦合度增加,维护起来更加困难。 1.2. 主要特点 单一职责原则(Single Responsibi…...
c语言学习,malloc()函数分析
1:malloc() 函数说明: 申请配置size大小内存空间 2:函数原型: void *malloc(size_t size) 3:函数参数: 参数size,为申请内存大小 4:返回值: 配置成功则返回指针&#…...
【运维项目经历|041】上云项目-物理机迁移到阿里云
🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专家博主 💊交流社区:CSDN云计算交流社区欢迎您的加入! 目录 项目名称 项目背景 项目目标 项…...
分组并合并其它列的非空值 --Excel难题#83
Excel第1列是分类,第2-42列是平行的多个数据项列,下表用部分列示例。数据有X或null两种情况,同一个分类的同一列数据偶尔有重复。 ABCDE1IDCriteria1Criteria2Criteria3Criteria42FirstValueX3FirstValueX4FirstValueX5FirstValueX6SecondVa…...
VM相关配置及docker
NAT——VMnet8网卡 桥接——WLAN/网线 仅主机——VMnet1网卡 docker与虚拟机的区别 启动docker服务 systemctl start docker 重启 systemctl start docker关闭docker服务 systemctl stop docker.servicedocker的两大概念 镜像:images,应用程序的静态文…...
Redis中Set数据类型常用命令
目录 1. 添加元素 2. 移除元素 3. 检查成员是否存在 4. 获取集合成员 5. 获取集合成员数量 6. 随机获取集合中的一个成员 7. 集合运算 8. 集合的移值 9. 提供集合的随机元素 在Redis中,Set是一种无序且不重复的字符串集合。 1. 添加元素 SADD key member [member ..…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
