文章目录

    • 一、原型模式的概念
    • 二、原型模式的结构
    • 三、原型注册机制
    • 四、完整示例代码

一、原型模式的概念

  原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。通过复制(克隆)已有的实例来创建新的对象,而不是通过 new 来实例化。

  • 意图:在对象创建代价较大、或需要保留对象当前状态时,通过克隆来生成新对象。
  • 核心思想:每个类实现一个 clone() 接口,用于复制自身。

在这里插入图片描述
优点:

  • 隐藏对象创建细节,对客户端透明。
  • 提高性能(适合复杂对象复制)。
  • 动态扩展对象种类,不需要修改工厂类。

缺点:

  • 对象内部含有复杂引用时,深拷贝实现复杂。
  • 如果对象的构造过程并不复杂,使用原型模式反而增加代码复杂度。

二、原型模式的结构

角色组成:

  • Prototype(抽象原型类):定义了 clone() 方法的接口。
  • ConcretePrototype(具体原型类):实现 clone(),复制自身。
  • Client(客户类):通过调用 clone() 来创建新对象,而不是直接 new。

基本实现:
在这里插入图片描述
UML类图:
在这里插入图片描述
示例代码:

#include <iostream>
#include <string>
using namespace std;// 抽象原型类
class Prototype {
public:virtual ~Prototype() {}virtual Prototype* clone() const = 0;virtual void show() const = 0;
};// 具体原型类 A
class ConcretePrototypeA : public Prototype {
public:ConcretePrototypeA(const string& name) : name(name) {}Prototype* clone() const override {return new ConcretePrototypeA(*this); // 调用拷贝构造}void show() const override {cout << "ConcretePrototypeA: " << name << endl;}
private:string name;
};// 具体原型类 B
class ConcretePrototypeB : public Prototype {
public:ConcretePrototypeB(int value) : value(value) {}Prototype* clone() const override {return new ConcretePrototypeB(*this); // 调用拷贝构造}void show() const override {cout << "ConcretePrototypeB: value=" << value << endl;}
private:int value;
};// 使用示例
int main() {Prototype* p1 = new ConcretePrototypeA("原型A");Prototype* p2 = new ConcretePrototypeB(42);Prototype* c1 = p1->clone(); // 克隆APrototype* c2 = p2->clone(); // 克隆Bc1->show();c2->show();delete p1;delete p2;delete c1;delete c2;return 0;
}

原型模式(Prototype Pattern)示例,用来克隆 QWidget 界面
场景:

  • 有一个复杂的界面 CustomWidget(包含标签和按钮)。
  • 界面创建比较复杂,不想每次都 new。
  • 通过原型模式,我们直接 clone() 来复制已有的界面。

代码示例:

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QString>// ============ 抽象原型类 ============
class PrototypeWidget : public QWidget {
public:PrototypeWidget(QWidget *parent = nullptr) : QWidget(parent) {}virtual ~PrototypeWidget() {}virtual PrototypeWidget* clone() const = 0;  // 原型接口
};// ============ 具体原型类 ============
class CustomWidget : public PrototypeWidget {
public:CustomWidget(const QString &title, const QString &buttonText, QWidget *parent = nullptr): PrototypeWidget(parent), m_title(title), m_buttonText(buttonText) {QVBoxLayout *layout = new QVBoxLayout(this);m_label = new QLabel(m_title, this);m_button = new QPushButton(m_buttonText, this);layout->addWidget(m_label);layout->addWidget(m_button);setLayout(layout);resize(220, 120);}// 克隆自身PrototypeWidget* clone() const override {return new CustomWidget(m_title, m_buttonText);}// ====== 扩展功能:支持修改部分内容 ======void setTitle(const QString &title) {m_title = title;if (m_label) m_label->setText(m_title);}void setButtonText(const QString &text) {m_buttonText = text;if (m_button) m_button->setText(m_buttonText);}private:QString m_title;QString m_buttonText;QLabel *m_label{nullptr};QPushButton *m_button{nullptr};
};// ============ 使用示例 ============
int main(int argc, char *argv[]) {QApplication app(argc, argv);// 原型窗口CustomWidget *prototype = new CustomWidget("原型窗口", "点击我");prototype->setWindowTitle("原型窗口");prototype->move(100, 100);prototype->show();// 克隆窗口 1(修改标题和按钮文字)CustomWidget *w1 = static_cast<CustomWidget*>(prototype->clone());w1->setWindowTitle("克隆窗口 1");w1->setTitle("我是克隆1");w1->setButtonText("确认");w1->move(350, 100);w1->show();// 克隆窗口 2(只修改按钮文字)CustomWidget *w2 = static_cast<CustomWidget*>(prototype->clone());w2->setWindowTitle("克隆窗口 2");w2->setButtonText("取消");w2->move(600, 100);w2->show();return app.exec();
}

三、原型注册机制

基本实现:
在这里插入图片描述
UML类图:
在这里插入图片描述
示例:支持原型注册

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QString>
#include <QMap>// ============ 抽象原型类 ============
class PrototypeWidget : public QWidget {
public:PrototypeWidget(QWidget *parent = nullptr) : QWidget(parent) {}virtual ~PrototypeWidget() {}virtual PrototypeWidget* clone() const = 0;  // 原型接口
};// ============ 具体原型类 ============
class CustomWidget : public PrototypeWidget {
public:CustomWidget(const QString &title, const QString &buttonText, QWidget *parent = nullptr): PrototypeWidget(parent), m_title(title), m_buttonText(buttonText){QVBoxLayout *layout = new QVBoxLayout(this);m_label = new QLabel(m_title, this);m_button = new QPushButton(m_buttonText, this);layout->addWidget(m_label);layout->addWidget(m_button);setLayout(layout);resize(220, 120);}// 克隆自身PrototypeWidget* clone() const override {return new CustomWidget(m_title, m_buttonText);}// ====== 扩展功能:支持修改部分内容 ======void setTitle(const QString &title) {m_title = title;if (m_label) m_label->setText(m_title);}void setButtonText(const QString &text) {m_buttonText = text;if (m_button) m_button->setText(m_buttonText);}private:QString m_title;QString m_buttonText;QLabel *m_label{nullptr};QPushButton *m_button{nullptr};
};// ============ 原型管理器 ============
class PrototypeManager {
public:~PrototypeManager() {qDeleteAll(m_prototypes);}void registerPrototype(const QString &name, PrototypeWidget *prototype) {if (m_prototypes.contains(name)) {delete m_prototypes[name];}m_prototypes[name] = prototype;}PrototypeWidget* create(const QString &name) {if (m_prototypes.contains(name)) {return m_prototypes[name]->clone();}return nullptr;}private:QMap<QString, PrototypeWidget*> m_prototypes;
};// ============ 使用示例 ============
int main(int argc, char *argv[]) {QApplication app(argc, argv);PrototypeManager manager;// 注册不同类型的窗口原型manager.registerPrototype("login", new CustomWidget("登录窗口", "登录"));manager.registerPrototype("register", new CustomWidget("注册窗口", "注册"));manager.registerPrototype("alert", new CustomWidget("警告", "确定"));// 克隆出 登录窗口CustomWidget *w1 = static_cast<CustomWidget*>(manager.create("login"));if (w1) {w1->setWindowTitle("克隆 - 登录");w1->move(100, 100);w1->show();}// 克隆出 注册窗口,并修改按钮文字CustomWidget *w2 = static_cast<CustomWidget*>(manager.create("register"));if (w2) {w2->setWindowTitle("克隆 - 注册");w2->setButtonText("立即注册");w2->move(350, 100);w2->show();}// 克隆出 警告窗口CustomWidget *w3 = static_cast<CustomWidget*>(manager.create("alert"));if (w3) {w3->setWindowTitle("克隆 - 警告");w3->move(600, 100);w3->show();}return app.exec();
}

四、完整示例代码

假设有一套 图形(Shape)类,包含圆形(Circle)、矩形(Rectangle),需要通过原型拷贝的方式创建新对象。

#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <QMap>// Prototype 接口
class Shape {
public:virtual ~Shape() {}virtual Shape* clone() const = 0;virtual void draw() const = 0;
};// 具体原型类:圆形
class Circle : public Shape {
public:Circle(int r = 0) : radius(r) {}Circle(const Circle& other) { radius = other.radius; }Shape* clone() const override {return new Circle(*this); // 深拷贝}void draw() const override {qDebug() << "绘制一个圆, 半径 =" << radius;}private:int radius;
};// 具体原型类:矩形
class Rectangle : public Shape {
public:Rectangle(int w = 0, int h = 0) : width(w), height(h) {}Rectangle(const Rectangle& other) {width = other.width;height = other.height;}Shape* clone() const override {return new Rectangle(*this);}void draw() const override {qDebug() << "绘制一个矩形, 宽 =" << width << " 高 =" << height;}private:int width;int height;
};// PrototypeManager 原型管理器
class PrototypeManager {
public:void registerPrototype(const QString& name, Shape* prototype) {prototypes[name] = prototype;}void unregisterPrototype(const QString& name) {prototypes.remove(name);}Shape* create(const QString& name) {if (prototypes.contains(name)) {return prototypes[name]->clone();}return nullptr;}private:QMap<QString, Shape*> prototypes;
};// 客户端使用
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);PrototypeManager manager;// 注册原型manager.registerPrototype("circle", new Circle(10));manager.registerPrototype("rectangle", new Rectangle(20, 30));// 克隆对象Shape* c1 = manager.create("circle");Shape* r1 = manager.create("rectangle");if (c1) c1->draw();if (r1) r1->draw();// 再次克隆,得到新的对象Shape* c2 = manager.create("circle");if (c2) c2->draw();// 清理内存delete c1;delete r1;delete c2;return a.exec();
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统网络管理

一、网络参数配置1、图形化配置#开启 [rootlocalhost ~]# systemctl start NetworkManager #关闭 [rootlocalhost ~]# systemctl stop NetworkManager #关闭并开机不自启 [rootlocalhost ~]# systemctl disable --now NetworkManager #开启并开机自启 [rootlocalhost ~]# syste…

服务器初始化

服务器初始化文章目录服务器初始化1. 配置国内 Yum 源&#xff08;加速软件安装&#xff09;2. 更新系统与安装必备工具3. 网络连接验证4. 配置主机名5. 同步时间6. 配置防火墙 (两种方式)6.1 iptables整体思路详细步骤第 1 步&#xff1a;停止并禁用 Firewalld第 2 步&#xf…

基于YOLOv11训练无人机视角Visdrone2019数据集

【闲鱼服务】 基于YOLOv11训练无人机视角Visdrone2019数据集Visdrone2019数据集介绍数据集格式数据预处理yolov11模型训练数据分布情况可视化训练结果Visdrone2019数据集介绍 VisDrone 数据集 是由中国天津大学机器学习和数据挖掘实验室 AISKYEYE 团队创建的大规模基准。它包含…

基于Springboot 的智能化社区物业管理平台的设计与实现(代码+数据库+LW)

摘 要随着智慧社区的普及&#xff0c;传统的物业管理方式已经无法满足现代社区的需求。目前&#xff0c;很多社区管理中存在信息不畅通、工作效率低以及居民服务体验不佳等问题。为了解决这些问题&#xff0c;我们基于SpringBoot框架开发了一套智能化社区物业管理平台&#xf…

【深度学习新浪潮】SAM 2实战:Meta新一代视频分割模型的实时应用与Python实现

引言:从图像到视频的分割革命 上周AI领域最引人注目的计算机视觉进展,当属Meta在SAM(Segment Anything Model)基础上推出的SAM 2模型持续引发的技术热潮。尽管SAM 2最初发布于2024年,但最新更新的2.1版本(2024年9月发布)凭借其突破性的实时视频分割能力,在自动驾驶、影…

sqli-labs靶场安装与使用指导教程(3种方法:通用版、php7版、Docker版)

目录 一、SQLI-LABS靶场 1、核心特点 2、关卡难度 二、源码安装法 1、开启Web服务和数据库服务 2、靶场源码下载 &#xff08;1&#xff09;通用版本 &#xff08;2&#xff09;PHP7版本 3、部署sqli-labs靶场 &#xff08;1&#xff09;确认网站根目录位置 &#x…

从零开始配置前端环境及必要软件安装

从零开始配置前端环境及必要软件安装一、安装编辑器二、安装浏览器三、安装Git版本控制工具四、Node.js 和 npm 环境变量配置1. 安装 Node.js 和 npm2. 配置全局模块和缓存目录3. 设置环境变量4. 更换 npm 镜像源5. 测试配置五、hosts文件六、辅助应用markdown&#xff08;笔记…

神经网络模型搭建及手写数字识别案例

代码实现&#xff1a;import torch print(torch.__version__) from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensor training_data datasets.MNIST(rootdata,trainTrue,downloadTru…

CRMEB标准版PC扫码登录配置教程(PHP版)

需要在开放平台创建网站应用 微信开放平台地址&#xff1a;https://open.weixin.qq.com/ 1、注册网站应用 2、填写信息&#xff0c;网站地址填写前台访问的域名就行 3、复制开放平台AppId和开放平台AppSecret 4、粘贴到后台应用配置的PC站点配置里

AmazeVault 核心功能分析,认证、安全和关键的功能

系列文章目录 Amazevault 是一款专注于本地安全的桌面密码管理器 AmazeVault 核心功能分析&#xff0c;认证、安全和关键的功能 AmazeVault 快速开始&#xff0c;打造个人专属桌面密码管理器 文章目录系列文章目录前言一、认证系统核心组件图形解锁实现图形锁控件 (PatternLoc…

Coze用户账号设置修改用户昵称-后端源码

前言 本文将深入分析Coze Studio项目的用户昵称修改功能后端实现&#xff0c;通过源码解读来理解整个昵称更新流程的架构设计和技术实现。用户昵称修改作为用户个人信息管理系统的重要组成部分&#xff0c;主要负责处理用户显示名称的更新和管理。 昵称修改功能相对简单但不失重…

基于WebTransport(底层QUIC)实现视频传输(HTML+JavaScript)

工作目录和基本操作见博客《基于HTTP3的WebTransport实践》&#xff0c;在此仅展示服务器端和客户端代码。 服务器端 import { readFile } from "node:fs/promises"; import { createServer } from "node:https"; import {Server} from "socket.io&qu…

Git 怎么仓库迁移?error: remote origin already exists.怎么解决

1. 确认本地已经有完整的 旧 仓库你本地应该有旧的项目&#xff0c;并且能看到 .git 文件夹。如果没有&#xff0c;可以先从旧仓库克隆下来&#xff1a;git clone 旧仓库git地址 cd 旧代码目录比如&#xff1a;git clone https://gitee.com/star-information/esflow-pro-api.gi…

【语法】【C+V】本身常用图表类型用法快查【CSDN不支持,VSCODE可用】

文章目录Mermaid 简介Mermaid 由三部分组成Mermaid 的使用方法复杂图表结构的技巧饼图简介饼图语法饼图示例雷达图简介雷达图语法雷达图语法细节标题轴曲线选项雷达图示例时间线简介时间线语法时间线示例树形图简介树形图语法树形图示例数据包图简介数据包图语法1&#xff1a;数…

Anaconda下载安装教程(附Anaconda安装包)

Anaconda下载安装教程&#xff08;附Anaconda安装包&#xff09;获取&#xff1a;python开发工具包丨夸克网盘-资源免费下载 有位小粉丝刚刚入门python&#xff0c;问我怎么安装Anaconda&#xff0c;于是我帮他找了一个详细的Anaconda安装教程和安装包。 Anaconda其实是一个p…

那我现在有3个输入 9层神经元 每层神经元数为 3 9 3 5 6 2 3 9 8 请给出我所有的权重矩阵

问题1 那我现在有3个输入 9层神经元 每层神经元数为 3 9 3 5 6 2 3 9 8 请给出我所有的权重矩阵 明白&#xff0c;我们来系统地列出你的 9层全连接网络 的权重矩阵。1️⃣ 网络结构 输入层&#xff1a;3 个神经元隐藏层/输出层&#xff1a;9 层神经元数分别为 [3,9,3,5,6,2,3,9…

广东省省考备考(第八十七天8.26)——判断推理(听课后强化训练)

判断推理&#xff1a;定义判断 错题解析 第一步&#xff1a;找出定义关键词。 “农村中各项经济活动及由此产生的经济关系”、“同农业有直接或间接的关系”。 第二步&#xff1a;逐一分析选项。 A项&#xff1a;该项指出具体的夏粮产量和增量&#xff0c;其中生产粮食属于种植…

读取 STM32H5 Data Flash 触发 NMI 的问题解析 LAT1544

关键字&#xff1a;STM32H5, data flash&#xff0c; high-cycle data, NMI问题描述客户反馈&#xff0c;使用 STM32H563 的 data flash(high-cycle data flash)&#xff0c;在还没有写入任何数据之前去读取 data flash, 会触发 hardfault 异常。1. 问题分析我们尝试在 NUCLEO-…

学云计算还是网络,选哪个好?

云计算工程师和网络工程师&#xff0c;都是IT界香饽饽&#xff0c;但方向差很大&#xff01;选错路后悔3年&#xff01;今天极限二选一&#xff0c;帮你彻底搞懂工作职责 网络工程师&#xff1a;网络世界的交警工程师&#xff01;主要管物理网络和逻辑连接。负责设计、搭建、维…

Matlab使用——开发上位机APP,通过串口显示来自单片机的电压电流曲线,实现光伏I-V特性监测的设计

预览此处的测试数据的采集频率和曲线变化是通过更换电阻来测试的&#xff0c;所以电压电流曲线显示并不是很平滑&#xff0c;图中可以看到每一个采集点的数值。这个设计是福州大学第三十期SRTP的一个校级的项目&#xff0c;打算通过分布式的在线扫描电路低成本的单片机&#xf…