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

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)设计模式

文章目录 一.什么是原型设计模式&#xff1f;二.原型模式的特点三.原型模式的结构四.原型模式的优缺点五.原型模式的 C 实现六.原型模式的 Java 实现七. 代码解析八.总结 类图&#xff1a; 原型设计模式类图 一.什么是原型设计模式&#xff1f; 原型模式&#xff08;Prototype…...

Qt—QLineEdit 使用总结

文章参考:Qt—QLineEdit 使用总结 一、简述 QLineEdit是一个单行文本编辑控件。 使用者可以通过很多函数,输入和编辑单行文本,比如撤销、恢复、剪切、粘贴以及拖放等。 通过改变 QLineEdit 的 echoMode() ,可以设置其属性,比如以密码的形式输入。 文本的长度可以由 m…...

go-zero使用自定义模板实现统一格式的 body 响应

前提 go环境的配置、goctl的安装、go-zero的基本使用默认都会 需求 go-zero框架中&#xff0c;默认使用goctl命令生成的代码并没有统一响应格式&#xff0c;现在使用自定义模板实现统一响应格式&#xff1a; {"code": 0,"msg": "OK","d…...

BUGKU printf

整体思路 实现循环-->获取libc版本和system函数地址->将strcpy的got表项修改为system并获得shell 第一步&#xff1a;实现循环 从汇编语句可以看出&#xff0c;在每次循环结束时若0x201700处的值是否大于1则会继续循环。 encode1会将编码后的结果保存至0x2015c0处&am…...

深度学习:梯度下降法

损失函数 L&#xff1a;衡量单一训练样例的效果。 成本函数 J&#xff1a;用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b &#xff1f; 成本函数J是参数w和b的函数&#xff0c;它被定义为平均值&#xff1b; 损失函数L可以衡量你的算法效果&a…...

`console.log`调试完全指南

大家好&#xff0c;这里是 Geek技术前线。 今天我们来探讨 Console.log() 的一些优点。并分析一些基本概念和实践&#xff0c;这些可以让我们的调试工作变得更加高效。 理解前端 log 与后端 log 的区别 前端 log 与后端 log 有着显著的不同&#xff0c;理解这一点至关重要。…...

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多页面打包

需求&#xff1a;把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤&#xff1a; 准备源码&#xff08;html、css、js&#xff09;放入相应位置&#xff0c;并改用模块化语法导出 原始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 引用执行运行时绑定)

说一下情况&#xff1a; 代码没问题&#xff0c;能成功从数据库里查到数据&#xff0c;能将数据丢给ViewBag.XXXX, 在View页面也能获取到 ViewBag.XXXX的值&#xff0c;但是发布到线上后报这个错&#xff1a; Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 无法对 …...

VUE 入门级教程:开启 Vue.js 编程之旅

一、Vue.js 简介 Vue.js 是一套构建用户界面的渐进式 JavaScript 框架。它专注于视图层的开发&#xff0c;能够轻松地与其他库或现有项目进行整合。Vue.js 的核心库只关注视图层&#xff0c;通过简洁的 API 实现数据绑定和 DOM 操作的响应式更新&#xff0c;让开发者可以高效地…...

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 如果报错&#xff0c;Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc&#xff0c;最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...

机器学习——生成对抗网络(GANs):原理、进展与应用前景分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一. 生成对抗网络的基本原理二. 使用步骤2.1 对抗性训练2.2 损失函数 三. GAN的变种和进展四. 生成对抗网络的应用五. 持续挑战与未来发展方向六. 小结 前言 生…...

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…...

Ps:存储 Adobe PDF

在 Adobe Photoshop 中&#xff0c;将图像保存为 PDF 文件时&#xff0c; 会弹出“存储 Adobe PDF” Save Adobe PDF对话框。在此对话框中提供了多个选项&#xff0c;用于控制 PDF 文件的输出&#xff0c;包括一般设置&#xff08;选择预设、兼容性和保留编辑功能&#xff09;、…...

DDR3保姆级使用教程:ZYNQ 7010

内容:使用DDR3 IP核&#xff0c;向DDR3写入数据&#xff0c;然后再读出数据&#xff0c;通过串口打印。 设备&#xff1a;ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 &#xff08;1&#xff09;工程模块&#xff1a;一个写FIFO&#xff0c;一个读FIFO。一个ZYNQ IP核&am…...

OpenCV 模板匹配全解析:从单模板到多模板的实战指南

简介&#xff1a;本文深入探讨 OpenCV 中的模板匹配技术。详细介绍构建输入图像与模板图像的步骤&#xff0c;包括读取、截取、滤波与存储等操作。剖析 cv2.matchTemplate 语法及其参数含义&#xff0c;阐述不同匹配方法下结果值的意义。同时讲解 cv2.minMaxLoc 语法&#xff0…...

【JAVA] 杂谈: java中的拷贝(克隆方法)

这篇文章我们来介绍什么是拷贝&#xff0c;并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝&#xff1a; 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图&#xff1a;​ 1.3 浅拷贝的不足 1.3.1 增加引用…...

使用 PDF API 合并 PDF 文件

内容来源&#xff1a; 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户&#xff0c;该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...