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

news2024/12/23 22:37:56

一,原型模式的定义

原型模式是一种创建型设计模式,它允许通过克隆已有对象来创建新对象,从而无需调用显式的实例化过程。

原型模式的设计,使得它可以创建一个与原型对象相同或类似的新对象,同时又可以减少对象实例化操作产生的性能开销,使得创建对象的操作更加便捷,它减少了大量不必要的重复工作,并提高了系统性能。

当创建对象的操作比较复杂和耗时的时候,原型模式则提供了一个更加高效和简单的创建对象的模式,它可以更加快速的创建对象的副本,且不需要依赖对象的某些实例化步骤,它避免了使用传统的new关键字创建对象实例时的复杂构造过程。

原型模式的主要缺点则是原型对象必须预先存在于系统中,并且需要预先进行注册。此时,如果有大量的原型对象需要被创建,并且每个原型对象都需要进行自定义,维护和管理这些原型对象可能会变得很复杂。

原型模式在现实生活中的抽象实例:

图形绘制:假设我们需要绘制不同形状的图形,可以定义一个图形类作为原型,然后通过克隆该原型对象来创建具体的图形对象。

陶艺制作:先制作一个陶艺原型作为参考,然后通过复制或克隆原型来制作出多个相似的陶艺品。

服装设计:设计师预先设计一套成衣样板,然后通过复制或克隆样板来制作出多件相似或不同款式的服装。

二,原型模式的结构

原型模式主要包含以下组件:

1.抽象原型(Prototype):定义克隆方法的接口,具体原型类通过实现这些方法来提供其自身的副本。

2.具体原型(ConcretePrototype):包含抽象原型类的具体实现,它会提供一个复制自身的方法,该方法将创建并返回一个对象副本。

3.客户端(Client):客户端使用原型类来创建新对象的副本,它会先获取原型对象,并使用原型对象的克隆方法来创建新的对象实例。

组件之间的工作步骤如下:

1.客户端通过实例化具体原型类,并调用其克隆方法来创建一个原型对象。

2.原型对象调用自身的克隆方法,将自身复制一份,返回一个克隆的对象。

3.客户端获取到克隆对象后,可以根据自身的业务需求对其进行进一步的修改和使用。

对应UML类图:

三,原型模式代码样例

Demo1:

#include <iostream>
#include <string>

//定义原型基类
class Prototype {
public:
    virtual ~Prototype() {}
    virtual Prototype* clone() const = 0;
    virtual void print() const = 0;
};

//定义具体原型类
class ConcretePrototype : public Prototype{
private:
    std::string name;
public:
    ConcretePrototype(const std::string& name) : name(name) {}
    Prototype* clone() const override {
        return new ConcretePrototype(*this);
    }
    void print() const override {
        std::cout << "Prototype: " << name << std::endl;
    }
};

int main() {
    //创建原型对象
    ConcretePrototype prototype("Original");
    //使用原型对象创建新对象
    Prototype* clone = prototype.clone();
    clone->print();
    //释放内存
    delete clone;
    return 0;
}

运行结果:

Prototype: Original

Demo2:

#include <iostream>
#include <string>

class Prototype {
public:
    virtual ~Prototype() {}
    virtual Prototype* clone() const = 0;
    virtual void info() const = 0;
};

class ConcretePrototypeA: public Prototype {
public:
    ConcretePrototypeA(int id, std::string name)
        : m_id(id), m_name(name) {}
    Prototype* clone() const override {
        return new ConcretePrototypeA(*this);
    }
    void info() const override {
        std::cout << "ConcretePrototypeA: id = "
                  << m_id << ", name = " 
                  << m_name <<  std::endl;
    }
private:
    int m_id;
    std::string m_name;
};

class ConcretePrototypeB: public Prototype {
public:
    ConcretePrototypeB(std::string description)
        : m_description(description) {}
    Prototype* clone() const override {
        return new ConcretePrototypeB(*this);
    }
    void info() const override {
        std::cout << "ConcretePrototypeB: description = " 
                  << m_description <<  std::endl;
    }
private:
    std::string m_description;
};

int main() {
    ConcretePrototypeA* prototypeA = new ConcretePrototypeA(1, "First");
    Prototype* cloneA = prototypeA->clone();
    cloneA->info();
    ConcretePrototypeB* prototypeB = new ConcretePrototypeB("This is a prototype");
    Prototype* cloneB = prototypeB->clone();
    cloneB->info();
    delete prototypeA;
    delete cloneA;
    delete prototypeB;
    delete cloneB;
    return 0;
}

运行结果:

ConcretePrototypeA: id = 1, name = First
ConcretePrototypeB: description = This is a prototype

四,原型模式的应用场景

图形用户界面:创建可定制的控件,如Windows的对话框,设计一个原型控件,让用户根据需求选择属性进行定制。

文本编辑器开发:支持“剪切”、“复制”、“粘贴”的功能,使用已存在的文档作为复制和创建新文档的原型。

数据库开发:将数据库的某个状态视为原型,当需要创建新的数据库版本时,可以直接从这个原型复制。

配置工具开发:基于原型模式帮助快速生成配置对象,而无需每次都新建一个空的配置。

Web应用程序:让用户可以在原型基础上添加、修改字段,动态生成表单元素。

五,原型模式的优缺点

原型模式的优点:

简化了对象的创建过程,使得代码更加简洁且易于维护。

提高了动态创建对象和销毁对象的效率。

封装和隐藏了创建对象的细节。

减少了对构造函数的直接调用,提高了代码的性能。

支持灵活的定制具体对象的属性和方法。

原型模式的缺点:

需要实现克隆对象的接口。

需要配合深拷贝或浅拷贝来使用,可能会导致引用对象的复制。

有的原型模式基于递归的方式来克隆对象,可能会引起堆栈溢出的问题。

针对大型对象的复制,会占用特别多的内存。

六,代码实战

Demo1:基于智能指针封装的原型模式:

#include <memory>
#include <iostream>

class Prototype {
public:
    virtual std::unique_ptr<Prototype> clone() const = 0;
    void printValue() const {
        std::cout << "Origin Value." << std::endl;
    }
};

class ConcretePrototype : public Prototype {
private:
    int value;
public:
    ConcretePrototype(int v) : value(v) {}
    std::unique_ptr<Prototype> clone() const override {
        return std::make_unique<ConcretePrototype>(value);
    }
    void printValue() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    auto prototype = std::make_unique<ConcretePrototype>(5);
    auto clonedPrototype = prototype->clone();
    prototype->printValue();
    clonedPrototype->printValue();
    return 0;
}

运行结果:

Value: 5
Origin Value.

Demo2:基于工厂的方式管理各种原型

#include <iostream>
#include <string>
#include <map>

class Prototype {
public:
    int data;
    std::string name;
    Prototype(int data, const std::string& name) : data(data), name(name) {}
    virtual Prototype* clone() {
        return new Prototype(*this);
    }
};

class PrototypeFactory {
private:
    std::map<std::string, Prototype*> prototypes;
public:
    PrototypeFactory() {
        prototypes["original"] = new Prototype(40, "Original");
        prototypes["copy"] = new Prototype(100, "Copy");
    }
    Prototype* create(const std::string& type) {
        return prototypes[type]->clone();
    }
};

int main() {
    PrototypeFactory factory;
    Prototype* original = factory.create("original");
    Prototype* copy = factory.create("copy");

    std::cout << "Original: data="
              << original->data
              << ", name="
              << original->name << std::endl;
    std::cout << "Copy: data="
              << copy->data
              << ", name="
              << copy->name << std::endl;

    delete original;
    delete copy;
    return 0;
}

运行结果:

Original: data=40, name=Original
Copy: data=100, name=Copy

七,参考阅读

https://softwarepatterns.com/cpp/prototype-software-pattern-cpp-example

https://www.geeksforgeeks.org/prototype-design-pattern/

https://www.tutorialspoint.com/design_pattern/prototype_pattern.html

https://sourcemaking.com/design_patterns/prototype

https://softwareparticles.com/design-patterns-prototype/

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

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

相关文章

项目实战应用Redis分布式锁

Redis分布式锁 一、前言二、Redis分布式锁过期处理三、Redis分布式实现3.1 基于Jedis 的API实现分布式锁3.1.1 基础命令3.1.2 基于Jedis API的分布式锁3.1.3 基于Lua脚本实现分布式锁 四、Redisson的使用五、Redision锁 核心源码分析六、总结 一、前言 对于项目中使用Redis分布…

jdk相关介绍

JDK&#xff0c;全称Java Development Kit&#xff0c;是Java语言开发的基础工具包。它包含了Java运行时环境&#xff08;JRE&#xff09;以及用于开发Java应用程序的各种工具和库。JDK为Java程序员提供了编译、调试和运行Java应用程序所需的全部环境。 JDK的主要组成部分包括&…

OpenCV_图像像素读写操作

本文详细介绍了如何在C项目中使用OpenCV进行图像像素的读写操作&#xff0c;包括使用头文件声明Pixel类&#xff0c;通过遍历和指针方式处理灰度图和彩色图&#xff0c;以及在主函数中调用这些操作。 数组遍历的方式进行图像像素读写 void QuickDemo::pixelVisit_Demo(Mat&am…

【最新华为OD机试E卷-支持在线评测】增强的strstr(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

替换 Oracle ,江河信息用 TDengine 解决高基数查询写入问题

在数字经济快速发展的背景下&#xff0c;智慧水利作为重要的基础设施之一&#xff0c;正逐步成为提升水资源管理效率、优化生态环境的重要力量。江西省水投江河信息技术有限公司&#xff08;以下简称“江河信息”&#xff09;作为高新技术国有企业&#xff0c;坚定致力于打造数…

监控binlog日志监控表变化进行消息通知

前言 由于我们做项目的时候有项目任务管理工具&#xff0c;目前用的最多的是禅道&#xff0c;而我们用的是redmine&#xff0c;而redmine是使用ruby写的&#xff0c;刚好我们这边没有会用ruby的人&#xff0c;所以就有了这样一个小工具&#xff0c;用于监控binlog日志通过钉钉…

机器人相关知识的本身和价值

简要将人类简史分为 农业工业信息智能 四个时代。 在信息时代&#xff0c;知识本身就可以等同于价值。 常识看&#xff0c;学历可以变现&#xff0c;高品质文凭能极大概率获得工资远远高于平均值的工作机会。 在智能时代&#xff0c;知识本身毫无价值&#xff0c;知识的应…

UML 类图(提供 Java 实现)

文章目录 UML 类图概述及作用类图表示法类&#xff08;接口&#xff09;的表示类与类之间关系的表示关联关系&#xff08;Association&#xff09;单向关联&#xff08;Unidirectional Association&#xff09;双向关联&#xff08;Bidirectional Association&#xff09;自关联…

大学生看过来,必备4款写论文AI写作网站先稿后付

在当今学术研究和写作领域&#xff0c;AI论文写作工具的出现极大地提高了写作效率和质量。这些工具不仅能够帮助研究人员快速生成论文草稿&#xff0c;还能进行内容优化、查重和排版等操作。其中&#xff0c;千笔-aipasspaper是一个备受推荐的平台&#xff0c;它结合了先稿后付…

7.2 溪降技术:下攀

目录 7.2 下攀概述视频课程观看电子书&#xff1a;下攀 一级风险评估装备个人动作技术:面壁下攀烟囱下攀 协助队友总结 7.2 下攀 概述 下攀可能是峡谷探险中最被低估的技能。峡谷中经常存在可以下攀的小落差&#xff0c;这种方式比设置绳索快得多。一组熟练的下攀者能迅速完成…

JavaScript高级——闭包的理解

1、如何产生闭包&#xff1f; —— 当一个嵌套的内部&#xff08;子&#xff09;函数引用了嵌套的外部&#xff08;父&#xff09;函数的变量&#xff08;函数&#xff09;时&#xff0c;就产生了闭包。 2、闭包到底是什么&#xff1f; —— 使用 chrome 查看 —— 理解一&a…

字符编码发展史1 — ASCII和EASCII

1. 字符集与字符编码 1.1. 字符集1.2. 字符编码1.3. 两者的关系 2. 字符编码的发展历史 2.1. 第一个阶段 ASCII编码 2.1.1. ASCII2.1.2. EASCII 1. 字符集与字符编码 1.1. 字符集 字符集&#xff08;Charcater Set或Charset&#xff09;&#xff1a; 是一个系统支持的所有…

【AI小项目5】使用 KerasNLP 对 Gemma 模型进行 LoRA 微调

目录 一、项目简介概述时间主要工作和收获技术栈数据集结果参考 二、完整代码概览设置安装依赖选择一个后端导入包 加载数据集加载模型微调前的推理欧洲旅行例子光合作用例子 LoRA 微调微调后的推理欧洲旅行例子光合作用例子 改进方向 三、背景知识补充Fine-tune&#xff08;微…

数据结构(2):LinkedList和链表[2]

我们在上一篇文章中着重讨论了单链表的实现。其中我们要注意单链表进行遍历时一步一步走的思想。那么这篇文章我们将继续讨论链表的更多内容&#xff0c;那就让我们开始吧。 1.经典单链表算法题 我们将通过几个经典的题对单链表进行进一步的认识。 (1)反转链表 206. 反转链…

2024年上海初中生古诗文大会倒计时一个半月:做一做2024官方模拟题

2024年上海市初中生古诗文大会自由报名活动的初赛日期于11月3日开始&#xff0c;距离今天大概一个半月。 如何准备2024年初中生古诗文大会的自由报名初选呢&#xff1f;吃透&#xff08;记熟&#xff09;2024年初中生古诗文阅读专辑上的题目、知识点和往年真题及知识点。 有许…

Python数据分析-世界上最富有的1000人

一、研究背景 随着全球化的加速发展和技术的进步&#xff0c;财富分配问题日益成为全球关注的焦点。财富的不平等现象日益明显&#xff0c;少数极富有的个人掌握了全球大部分的财富资源。了解全球最富有个人的财富分布及其背后的行业和国家因素&#xff0c;对于分析全球经济趋…

Element-ui el-table 全局表格排序

实现效果如下&#xff1a; 一、当页数据排序 如果只想要当前页面排序&#xff0c;只会涉及到前端&#xff0c;只需在<el-table-column>标签上添加 :sortable"true"即可 二、自定义排序 如果想要全局排序&#xff0c;需要自定义排序函数&#xff0c;请求后台排…

Linux基础---10进程管理

一.查看和关闭进程 1.查看进程 基础指令: ps -efPID 进程编号&#xff0c;PPID 父进程编号&#xff0c; CMD命令名称 进阶指令–查看进程的树形结构&#xff1a; yum install psmisc -y #首先安装psmisc后可直接使用pstreepstree2.关闭进程 要想关闭某个或多个进程需要知道…

简洁明了!中缀表达式转为后缀表达式规则及代码

简单来说&#xff0c;就是弄两个栈&#xff0c;判断执行&#xff1a; 上代码&#xff1a; #include<iostream> #include<stack> #include<cstring> using namespace std; stack<char>s1,s2; char now; int main(){string c;cin>>c;for(int i0;…

微信视频号导出视频软件

最近研究了一下微信视频号导出视频的方法&#xff0c;目前发现还是比较难搞&#xff0c;查了一些资料&#xff0c;写了一个可以导出视频的软件&#xff0c;目前还不完善&#xff0c;但是导出视频到本地还是没问题&#xff0c;先用着吧&#xff0c;后期再完善。先记录一下。 测…