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

深入浅出设计模式——创建型模式之原型模式 Prototype

文章目录

  • 原型模式简介
  • 原型模式结构
  • 关于克隆方法:浅拷贝/深拷贝
  • 原型模式代码实例
    • 定义原型类和克隆方法
    • 客户端使用代码示例
      • 示例一:浅拷贝
    • 示例二:深拷贝
  • 原型模式总结
    • 开闭原则

代码仓库

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

定义看起来有点绕口,不妨简单的理解为:原型模式就是用来克隆对象的。

举个例子,比如有一天,周杰伦到奶茶店点了一份不加冰的原味奶茶,你说我是周杰伦的忠实粉,我也要一份跟周杰伦一样的。
在这里插入图片描述

即便Jungle读书少,Jungle也清晰地记得中学生物课本上提到过的克隆羊“多利”。虽然多利寿命不长,但它的出现对“克隆(Clone)”技术意义重大。克隆,直观说就是从原有生物体上取体细胞,然后无性繁殖出有完全相同基因的个体或种群。这么说来中国的克隆技术其实是世界领先的,因为孙悟空拔一根毫毛变出许多一模一样的孙悟空的传说本质上就是克隆!而本文将要介绍的原型模式,将克隆技术应用到了软件设计层面。

原型模式简介

原型模式通过复制一个已有对象来获取更多相同或者相似的对象。原型模式定义如下:

使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。

原型模式的工作原理是将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程。从工厂方法角度而言,创建新对象的工厂就是原型类自己。软件系统中有些对象的创建过程比较复杂,且有时需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在。

原型模式结构

在这里插入图片描述

关于克隆方法:浅拷贝/深拷贝

在这里插入图片描述

原型模式代码实例

明天就是周一了,Jungle又陷入了苦恼中,因为作业还没完成。于是Jungle想拿着哥哥Single的作业来抄一份。虽然抄袭作业并不好,但是边抄边学借鉴一下也是可以的。于是乎,Jungle开始动起手来……

作业包含几个部分:姓名(name)、学号(idNum)、模型(workModel)。首先定义一个workModel类:

// work model类
// 作为复杂的成员对象,供ConcreteWork引用。
class WorkModel {
public:std::string modelName;WorkModel() : modelName("") {}WorkModel(const std::string& iName) : modelName(iName) {}void setWorkModelName(const std::string& iName) {this->modelName = iName;}std::string getWorkModelName() const {return modelName;}// 深拷贝构造函数// 深拷贝构造函数防止多个对象共享同一个内存(避免浅拷贝问题)。// std::string 本身已经重载了拷贝构造函数和赋值运算符,实现了深拷贝的语义。WorkModel(const WorkModel& other) : modelName(other.modelName) {}
};  

该实例UML图如下:
在这里插入图片描述

定义原型类和克隆方法

// 抽象原型类PrototypeWork
// 定义抽象接口clone(),具体原型类必须实现该方法。
class PrototypeWork {
public:PrototypeWork() {}virtual ~PrototypeWork() {}virtual PrototypeWork* clone() = 0;virtual void printWorkInfo() const = 0;
};// 具体原型类PrototypeWork
class ConcreteWork: public PrototypeWork {
public:ConcreteWork(const string& iName, int iIdNum, const string& modelName): name(iName), idNum(iIdNum), workModel(new WorkModel(modelName)) {}// 深拷贝构造函数ConcreteWork(const ConcreteWork& other): name(other.name), idNum(other.idNum), workModel(new WorkModel(*other.workModel)) {}// 深拷贝赋值运算符// ConcreteWork& operator=(const ConcreteWork& other) {//     if (this != &other) {//         name = other.name;//         idNum = other.idNum;//         delete workModel;//         workModel = new WorkModel(*other.workModel);//     }//     return *this;// }// 克隆接口实现(返回深拷贝)PrototypeWork* clone() override {return new ConcreteWork(*this);}~ConcreteWork() {delete workModel;}// 打印work信息void printWorkInfo() const override {std::cout << "Name: " << name << std::endl;std::cout << "IdNum: " << idNum << std::endl;std::cout << "ModelName: " << workModel->getWorkModelName() << std::endl;}// 新增set方法void setName(const std::string& newName) {name = newName;}void setIdNum(int newIdNum) {idNum = newIdNum;}void setModel(WorkModel* newModel) {if (workModel != nullptr) {delete workModel;}workModel = newModel;}// 新增get方法std::string getName() const {return name;}int getIdNum() const {return idNum;}WorkModel* getModel() const {return workModel;}private:string name;int idNum;WorkModel* workModel;
};

客户端使用代码示例

示例一:浅拷贝

#include "PrototypePattern.h"int main() {
// #if 0
// // 下面的代码将不会被编译,也不会执行ConcreteWork *singleWork = new ConcreteWork("Single",1001,"Single_Model");printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\njungle直接抄作业……\n");ConcreteWork *jungleWork = singleWork;printf("\nJungle的作业:\n");jungleWork->printWorkInfo();// 抄完改名字和学号,否则会被老师查出来printf("\njungle抄完改名字和学号,否则会被老师查出来……\n");jungleWork->setName("jungle");jungleWork->setIdNum(1002);WorkModel *jungleModel = new WorkModel();jungleModel->setWorkModelName("Jungle_Model");jungleWork->setModel(jungleModel);// 检查下是否改对了printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\nJungle的作业:\n");jungleWork->printWorkInfo();
// #endif 
#if 0
// 下面的代码将不会被编译,也不会执行ConcreteWork *singleWork = new ConcreteWork("Single", 1001, "Single_Model");printf("\nSingle的作业:\n");// clone() 返回 PrototypeWork*,需类型转换ConcreteWork* jungleWork = dynamic_cast<ConcreteWork*>(singleWork->clone());printf("\njungle直接抄作业……\n");// 抄完改名字和学号,否则会被老师查出来printf("\njungle抄完改名字和学号,否则会被老师查出来……\n");jungleWork->setName("jungle");jungleWork->setIdNum(1002);WorkModel *jungleModel = new WorkModel();jungleModel->setWorkModelName("Jungle_Model");jungleWork->setModel(jungleModel);// 检查下是否改对了printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\nJungle的作业:\n");jungleWork->printWorkInfo();delete singleWork;delete jungleWork;
#endif return 0;
}

在这里插入图片描述
显然,这不是我们想要的结果。接下来我们使用clone方法。

示例二:深拷贝


```cpp
#include "PrototypePattern.h"int main() {
#if 0
// 下面的代码将不会被编译,也不会执行ConcreteWork *singleWork = new ConcreteWork("Single",1001,"Single_Model");printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\njungle直接抄作业……\n");ConcreteWork *jungleWork = singleWork;printf("\nJungle的作业:\n");jungleWork->printWorkInfo();// 抄完改名字和学号,否则会被老师查出来printf("\njungle抄完改名字和学号,否则会被老师查出来……\n");jungleWork->setName("jungle");jungleWork->setIdNum(1002);WorkModel *jungleModel = new WorkModel();jungleModel->setWorkModelName("Jungle_Model");jungleWork->setModel(jungleModel);// 检查下是否改对了printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\nJungle的作业:\n");jungleWork->printWorkInfo();
#endif 
// #if 0
// 下面的代码将不会被编译,也不会执行ConcreteWork *singleWork = new ConcreteWork("Single", 1001, "Single_Model");printf("\nSingle的作业:\n");singleWork->printWorkInfo();// clone() 返回 PrototypeWork*,需类型转换printf("\njungle直接抄作业……\n");ConcreteWork* jungleWork = dynamic_cast<ConcreteWork*>(singleWork->clone());printf("\nJungle的作业:\n");jungleWork->printWorkInfo();// 抄完改名字和学号,否则会被老师查出来printf("\njungle抄完改名字和学号,否则会被老师查出来……\n");jungleWork->setName("jungle");jungleWork->setIdNum(1002);WorkModel *jungleModel = new WorkModel();jungleModel->setWorkModelName("Jungle_Model");jungleWork->setModel(jungleModel);// 检查下是否改对了printf("\nSingle的作业:\n");singleWork->printWorkInfo();printf("\nJungle的作业:\n");jungleWork->printWorkInfo();delete singleWork;delete jungleWork;
// #endif return 0;
}

在这里插入图片描述

原型模式总结

在这里插入图片描述

开闭原则

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

http://www.dtcms.com/a/305850.html

相关文章:

  • 【MySQL 数据库】MySQL索引特性(二)页目录(B和B+树)(非)聚簇索引 索引操作
  • 李宏毅2025《机器学习》-第九讲:大型语言模型评测的困境与“古德哈特定律”**
  • java面向对象高级02——单例类(设计模式)
  • 数据分析师进阶——95页零售相关数据分析【附全文阅读】
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博评论IP地图可视化分析实现
  • 语言模型的评估指标整理
  • Python设计模式详解:策略模式(Strategy Pattern)实战指南
  • LRU (Least Recently Used) 缓存实现及原理讲解
  • Ubuntu22.04中搭建GN编译环境
  • 深入理解缓存淘汰策略:LRU vs LFU 完全解析
  • 2025 年 NOI 最后一题题解
  • LoongCollector 安全日志接入实践:企业级防火墙场景的日志标准化采集
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现裂缝的检测识别(C#代码UI界面版)
  • docker:将cas、tomcat、字体统一打包成docker容器
  • 工厂方法模式:从基础到C++实现
  • 自动驾驶车辆的敏捷安全档案
  • java web 对比使用注解方式和 web.xml 方式配置过滤器
  • 「日拱一码」043 机器学习-多目标预测可解释性
  • 解决Nginx的HTTPS跨域内容显示问题
  • 相亲小程序聊天与互动系统模块搭建
  • C语言:指针
  • 【刷题】东方博宜oj 1307 - 数的计数
  • Ubuntu安装和使用Anaconda
  • Linux信号机制:从生活化类比到技术实现的多维度解析
  • rabbitmq--默认模式(点对点)
  • android-PMS-包加载的顺序
  • eBPF 赋能云原生: WizTelemetry 无侵入网络可观测实践
  • Ubuntu22.04.1搭建php运行环境
  • 【C++】类和对象(中)拷贝构造、赋值重载
  • 【目标检测】d-fine模型部署