23种设计模式-原型(Prototype)设计模式
文章目录
- 一.什么是原型设计模式?
- 二.原型模式的特点
- 三.原型模式的结构
- 四.原型模式的优缺点
- 五.原型模式的 C++ 实现
- 六.原型模式的 Java 实现
- 七. 代码解析
- 八.总结
类图: 原型设计模式类图
一.什么是原型设计模式?
原型模式(Prototype Pattern) 是一种创建型设计模式,它通过复制现有对象来生成新对象,而不是通过实例化类来创建。这种模式基于对象的克隆机制,适用于需要频繁创建对象的场景,可以提高性能并减少复杂的初始化过程。
二.原型模式的特点
- 克隆对象:通过复制已有对象生成新对象,而非通过构造函数创建。
- 性能优化:避免复杂对象创建的高开销。
- 灵活性:可以动态添加或删除原型,而不影响其他对象。
三.原型模式的结构
- Prototype(抽象原型类):定义了克隆方法,通常是 clone() 方法。
- ConcretePrototype(具体原型类):实现抽象原型类的克隆方法。
- Client(客户端):调用克隆方法创建新对象,而无需关心对象的具体类型。

四.原型模式的优缺点
- 优点:
- 性能优势:克隆比重新创建对象效率更高。
- 动态性:无需编译时依赖类,可以在运行时动态生成对象。
- 避免依赖性:通过克隆机制,可以避免直接依赖类的构造函数。
- 缺点:
- 复杂性增加:需要正确实现克隆方法,尤其是深拷贝场景。
- 资源消耗:可能会为每个可克隆的对象维护克隆逻辑,导致类职责增多。
五.原型模式的 C++ 实现
#include <iostream>
#include <string>
#include <memory> // for smart pointers
using namespace std;// 抽象原型类
class Prototype {
public:virtual ~Prototype() = default;// 克隆方法(纯虚函数)virtual unique_ptr<Prototype> clone() const = 0;virtual void display() const = 0;
};// 具体原型类1
class ConcretePrototypeA : public Prototype {
private:string data; // 模拟一些状态
public:ConcretePrototypeA(string data) : data(data) {}// 克隆方法unique_ptr<Prototype> clone() const override {return make_unique<ConcretePrototypeA>(*this); // 调用拷贝构造函数}void display() const override {cout << "ConcretePrototypeA with data: " << data << endl;}
};// 具体原型类2
class ConcretePrototypeB : public Prototype {
private:int value; // 模拟一些状态
public:ConcretePrototypeB(int value) : value(value) {}// 克隆方法unique_ptr<Prototype> clone() const override {return make_unique<ConcretePrototypeB>(*this); // 调用拷贝构造函数}void display() const override {cout << "ConcretePrototypeB with value: " << value << endl;}
};// 客户端代码
void ClientCode(const Prototype& prototype) {auto clonedObject = prototype.clone(); // 克隆一个对象clonedObject->display(); // 显示克隆对象的内容
}int main() {// 创建原型对象ConcretePrototypeA prototypeA("PrototypeA Data");ConcretePrototypeB prototypeB(42);cout << "Cloning ConcretePrototypeA:" << endl;ClientCode(prototypeA);cout << "\nCloning ConcretePrototypeB:" << endl;ClientCode(prototypeB);return 0;
}
六.原型模式的 Java 实现
// 抽象原型类
abstract class Prototype implements Cloneable {public abstract Prototype clone();public abstract void display();
}// 具体原型类A
class ConcretePrototypeA extends Prototype {private String data;public ConcretePrototypeA(String data) {this.data = data;}@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported!");}}@Overridepublic void display() {System.out.println("ConcretePrototypeA with data: " + data);}
}// 具体原型类B
class ConcretePrototypeB extends Prototype {private int value;public ConcretePrototypeB(int value) {this.value = value;}@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone not supported!");}}@Overridepublic void display() {System.out.println("ConcretePrototypeB with value: " + value);}
}// 客户端代码
public class PrototypePatternExample {public static void main(String[] args) {// 创建原型对象ConcretePrototypeA prototypeA = new ConcretePrototypeA("PrototypeA Data");ConcretePrototypeB prototypeB = new ConcretePrototypeB(42);System.out.println("Cloning ConcretePrototypeA:");Prototype clonedA = prototypeA.clone();clonedA.display();System.out.println("\nCloning ConcretePrototypeB:");Prototype clonedB = prototypeB.clone();clonedB.display();}
}
七. 代码解析
- 抽象原型类(Prototype):
- 定义了一个 clone() 方法,用于生成当前对象的副本。
- 使用虚函数,使得派生类可以实现自己的克隆逻辑。
- 具体原型类(ConcretePrototypeA 和 ConcretePrototypeB):
- 实现了 clone() 方法,通过调用自身的拷贝构造函数完成对象的克隆。
- ConcretePrototypeA 和 ConcretePrototypeB 模拟了不同的数据成员,演示了克隆不同类型对象的效果。
- 客户端代码:
- 接收一个 Prototype 对象的引用,并通过调用 clone() 方法克隆出一个新对象。
- 客户端无需关心具体的类,只需通过 Prototype 接口调用克隆方法即可。
八.总结
原型模式通过克隆的方式创建新对象,而不依赖于类的构造函数。这种模式在需要频繁创建对象、或者需要动态生成对象的场景中非常有用。通过正确实现 clone() 方法,可以有效提高程序的灵活性和性能。然而,在实现复杂对象的深拷贝时,需要特别注意对象之间的依赖关系和资源管理,以避免潜在的错误。
应用场景:
- 复杂对象的创建:初始化需要耗费大量资源的对象可以通过克隆来生成新对象。
- 性能优化:避免使用构造函数或工厂方法重复创建对象。
- 动态对象管理:需要动态生成对象而不依赖具体类。
相关文章:
23种设计模式-原型(Prototype)设计模式
文章目录 一.什么是原型设计模式?二.原型模式的特点三.原型模式的结构四.原型模式的优缺点五.原型模式的 C 实现六.原型模式的 Java 实现七. 代码解析八.总结 类图: 原型设计模式类图 一.什么是原型设计模式? 原型模式(Prototype…...
Qt—QLineEdit 使用总结
文章参考:Qt—QLineEdit 使用总结 一、简述 QLineEdit是一个单行文本编辑控件。 使用者可以通过很多函数,输入和编辑单行文本,比如撤销、恢复、剪切、粘贴以及拖放等。 通过改变 QLineEdit 的 echoMode() ,可以设置其属性,比如以密码的形式输入。 文本的长度可以由 m…...
go-zero使用自定义模板实现统一格式的 body 响应
前提 go环境的配置、goctl的安装、go-zero的基本使用默认都会 需求 go-zero框架中,默认使用goctl命令生成的代码并没有统一响应格式,现在使用自定义模板实现统一响应格式: {"code": 0,"msg": "OK","d…...
BUGKU printf
整体思路 实现循环-->获取libc版本和system函数地址->将strcpy的got表项修改为system并获得shell 第一步:实现循环 从汇编语句可以看出,在每次循环结束时若0x201700处的值是否大于1则会继续循环。 encode1会将编码后的结果保存至0x2015c0处&am…...
深度学习:梯度下降法
损失函数 L:衡量单一训练样例的效果。 成本函数 J:用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b ? 成本函数J是参数w和b的函数,它被定义为平均值; 损失函数L可以衡量你的算法效果&a…...
`console.log`调试完全指南
大家好,这里是 Geek技术前线。 今天我们来探讨 Console.log() 的一些优点。并分析一些基本概念和实践,这些可以让我们的调试工作变得更加高效。 理解前端 log 与后端 log 的区别 前端 log 与后端 log 有着显著的不同,理解这一点至关重要。…...
ROS VSCode调试方法
VSCode 调试 Ros文档 1.编译参数设置 cd catkin_ws catkin_make -DCMAKE_BUILD_TYPEDebug2.vscode 调试插件安装 可在扩展中安装(Ctrl Shift X): 1.ROS 2.C/C 3.C Intelliense 4.Msg Language Support 5.Txt Syntax 3.导入已有或者新建ROS工作空间 3.1 导入工作…...
16 —— Webpack多页面打包
需求:把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤: 准备源码(html、css、js)放入相应位置,并改用模块化语法导出 原始content.html代码 <!DOCTYPE html> <html lang"en"><head&…...
微服务即时通讯系统的实现(服务端)----(3)
目录 1. 消息存储子服务的实现1.1 功能设计1.2 模块划分1.3 模块功能示意图1.4 数据管理1.4.1 数据库消息管理1.4.2 ES文本消息管理 1.5 接口的实现1.5.1 消息存储子服务所用到的protobuf接口实现1.5.2 最近N条消息获取接口实现1.5.3 指定时间段消息搜索接口实现1.5.4 关键字消…...
.net6.0 mvc 传递 model 实体参数(无法对 null 引用执行运行时绑定)
说一下情况: 代码没问题,能成功从数据库里查到数据,能将数据丢给ViewBag.XXXX, 在View页面也能获取到 ViewBag.XXXX的值,但是发布到线上后报这个错: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 无法对 …...
VUE 入门级教程:开启 Vue.js 编程之旅
一、Vue.js 简介 Vue.js 是一套构建用户界面的渐进式 JavaScript 框架。它专注于视图层的开发,能够轻松地与其他库或现有项目进行整合。Vue.js 的核心库只关注视图层,通过简洁的 API 实现数据绑定和 DOM 操作的响应式更新,让开发者可以高效地…...
Ubantu系统docker运行成功拉取失败【成功解决】
解决docker运行成功拉取失败 失败报错 skysky-Legion-Y7000-IRX9:~$ docker run hello-world docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head “http://%2Fvar%2Frun%2Fdocker.sock/_ping”: dial uni…...
mvn-mac操作小记
1.安装brew 如果报错,Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc,最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...
机器学习——生成对抗网络(GANs):原理、进展与应用前景分析
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一. 生成对抗网络的基本原理二. 使用步骤2.1 对抗性训练2.2 损失函数 三. GAN的变种和进展四. 生成对抗网络的应用五. 持续挑战与未来发展方向六. 小结 前言 生…...
「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏
本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字,应用会判断是否接近目标数字,并提供提示“高一点”或“低一点”,直到用户猜中目标数字。这个小游戏结合状态管理和用户交互,是一个入门级的互动应用示例。 关键词 UI互…...
Ps:存储 Adobe PDF
在 Adobe Photoshop 中,将图像保存为 PDF 文件时, 会弹出“存储 Adobe PDF” Save Adobe PDF对话框。在此对话框中提供了多个选项,用于控制 PDF 文件的输出,包括一般设置(选择预设、兼容性和保留编辑功能)、…...
DDR3保姆级使用教程:ZYNQ 7010
内容:使用DDR3 IP核,向DDR3写入数据,然后再读出数据,通过串口打印。 设备:ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 (1)工程模块:一个写FIFO,一个读FIFO。一个ZYNQ IP核&am…...
OpenCV 模板匹配全解析:从单模板到多模板的实战指南
简介:本文深入探讨 OpenCV 中的模板匹配技术。详细介绍构建输入图像与模板图像的步骤,包括读取、截取、滤波与存储等操作。剖析 cv2.matchTemplate 语法及其参数含义,阐述不同匹配方法下结果值的意义。同时讲解 cv2.minMaxLoc 语法࿰…...
【JAVA] 杂谈: java中的拷贝(克隆方法)
这篇文章我们来介绍什么是拷贝,并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝: 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图: 1.3 浅拷贝的不足 1.3.1 增加引用…...
使用 PDF API 合并 PDF 文件
内容来源: 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户,该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
