当前位置: 首页 > 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 ..…...

Comsol 薄板声辐射响应优化:激励位置与频率的协同效应

1. 薄板声辐射响应基础原理 当你用手指轻轻敲击一块金属薄板时&#xff0c;会听到清脆的声响。这个看似简单的现象背后&#xff0c;隐藏着复杂的声学原理。在Comsol仿真中&#xff0c;我们可以精确模拟这种声辐射响应&#xff0c;为声学设备设计提供科学依据。 薄板声辐射的本质…...

Windows屏保设置失效?解锁注册表权限的终极指南

1. 为什么你的Windows屏保设置突然失效了&#xff1f; 最近有没有遇到过这种情况&#xff1a;明明想设置个屏保保护隐私&#xff0c;却发现所有选项都变成灰色不可点击&#xff1f;这个问题我帮不少朋友解决过&#xff0c;其实90%的情况都是注册表权限在作怪。Windows系统有个特…...

570-‘基于坠落机制改进的混沌麻雀算法SSACD‘在23个标准测试函数上可直接运行Matlab语言

570-基于坠落机制改进的混沌麻雀算法SSACD在23个标准测试函数测试可直接运行 Matlab语言 改进点如下&#xff1a; 1.首先&#xff0c;引入Sinusoidal混沌映射和变尺度混沌策略对种群进行初始化&#xff0c;提高种群多样性使算法具备跳出局部最优解的能力 2.其次&#xff0c;引入…...

硬件医生养成记:用SMUDebugTool守护AMD Ryzen系统健康

硬件医生养成记&#xff1a;用SMUDebugTool守护AMD Ryzen系统健康 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…...

Ubuntu下基于simple-rtsp-server构建轻量级实时视频流媒体服务

1. 为什么选择simple-rtsp-server搭建流媒体服务 最近在给公司搭建内部监控系统时&#xff0c;我对比了市面上七八种RTSP服务器方案&#xff0c;最终选择了simple-rtsp-server。这个用纯C语言编写的轻量级服务器&#xff0c;编译后二进制文件只有几百KB&#xff0c;但性能却出乎…...

终极go2rtc流媒体解决方案:3分钟搭建多协议摄像头管理系统

终极go2rtc流媒体解决方案&#xff1a;3分钟搭建多协议摄像头管理系统 【免费下载链接】go2rtc Ultimate camera streaming application with support RTSP, RTMP, HTTP-FLV, WebRTC, MSE, HLS, MP4, MJPEG, HomeKit, FFmpeg, etc. 项目地址: https://gitcode.com/GitHub_Tre…...

保姆级教程:用Project AirSim的Python脚本,5分钟复现无人机深度图避障Demo

5分钟实战&#xff1a;用Project AirSim实现无人机深度图避障全流程指南 刚接触无人机仿真的开发者常会遇到一个困境&#xff1a;想快速验证某个算法效果&#xff0c;却被复杂的配置和代码绊住脚步。本文将带你用Project AirSim提供的Python脚本&#xff0c;在5分钟内跑通完整的…...

Dropout、DropConnect、Standout...12种正则化变种,到底该用哪个?一份给炼丹师的避坑指南

Dropout变种全景指南&#xff1a;从理论到实战的12种策略深度解析 当你的神经网络在验证集上表现不佳时&#xff0c;第一个跳入脑海的解决方案是什么&#xff1f;对于大多数从业者来说&#xff0c;Dropout无疑是正则化工具箱中的首选武器。但你是否知道&#xff0c;标准Dropout…...

open_clip多模态模型实战指南:从技术原理到产业落地

open_clip多模态模型实战指南&#xff1a;从技术原理到产业落地 【免费下载链接】open_clip An open source implementation of CLIP. 项目地址: https://gitcode.com/GitHub_Trending/op/open_clip 核心价值&#xff1a;为什么选择open_clip&#xff1f; 在当今AI应用…...

Ext2Read:Windows用户如何轻松读取Linux分区文件

Ext2Read&#xff1a;Windows用户如何轻松读取Linux分区文件 【免费下载链接】ext2read A Windows Application to read and copy Ext2/Ext3/Ext4 (With LVM) Partitions from Windows. 项目地址: https://gitcode.com/gh_mirrors/ex/ext2read 你是否遇到过这样的情况&a…...