重拾设计模式--原型模式

文章目录

  • 原型模式定义
  • 原型模式UML图
  • 优点
  • 缺点
  • 使用场景
  • C++ 代码示例
  • 深拷贝、浅拷贝

原型模式定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象;
核心中的核心就是 克隆clone ,后面讲
原型模式是一种创建型设计模式,它的主要意图是通过复制现有的对象实例来创建新的对象,而不是通过传统的使用构造函数来初始化创建。

原型模式UML图

在这里插入图片描述

优点

提高创建对象的效率:当创建一个对象的过程比较复杂,例如需要进行大量的初始化操作、读取配置文件等,如果采用传统的构造方式每次创建都要重复这些复杂过程,而原型模式通过复制已有对象,能快速创建新对象,节省时间和资源。
便于动态创建对象:可以在运行时根据已有对象动态生成新的对象,对于一些需要根据不同场景灵活生成相似对象的情况非常有用。

缺点

深拷贝和浅拷贝问题:在实现对象复制时,如果对象中包含指针等复杂成员,需要正确处理深拷贝和浅拷贝的情况,否则可能导致数据不一致等问题。比如浅拷贝只是简单复制指针,多个对象会指向同一块内存区域,修改一个对象的数据可能意外影响到其他对象。
每一个类都要配备克隆方法:要使用原型模式,需要在具体的类中实现克隆(复制)的相关方法,增加了代码编写和维护的工作量。

使用场景

对象创建成本高的情况:比如创建一个数据库连接对象,初始化过程涉及到加载驱动、配置参数、建立网络连接等复杂操作,后续需要多个相似的连接对象时,就可以用原型模式复制已有的连接对象来快速创建新的。
根据已有对象生成变体对象:例如在图形绘制系统中,已经绘制了一个圆形,要基于这个圆形生成几个大小、颜色等属性稍有不同的新圆形,通过原型模式复制已有圆形对象再进行属性修改就很方便。

C++ 代码示例

以下是一个简单的 C++ 代码示例来演示原型模式,这里假设有一个简单的 Shape(图形)类作为基类,有 Rectangle(矩形)类继承自它,通过原型模式来复制矩形对象:

#include <iostream>
#include <string>// 抽象基类,定义克隆接口
class Shape
{
public:virtual Shape* clone() = 0;virtual void draw() = 0;virtual ~Shape() {}
};// 具体的矩形类
class Rectangle : public Shape
{
private:int width;int height;
public:Rectangle(int w, int h) : width(w), height(h) {}// 实现克隆方法,返回一个新的矩形对象副本Shape* clone() override {return new Rectangle(*this);}void draw() override{std::cout << "Drawing a rectangle with width: " << width << " and height: " << height << std::endl;}
};int main() 
{Rectangle originalRect(10, 20);originalRect.draw();// 通过原型模式复制矩形对象Shape* clonedRect = originalRect.clone();clonedRect->draw();delete clonedRect;char t;std::cin>>t;return 0;
}

在这里插入图片描述

在上述代码中:
首先定义了抽象基类 Shape,它有一个纯虚函数 clone 用于克隆对象,还有一个纯虚函数 draw 用于绘制图形(这里只是简单输出图形相关信息示意)。
Rectangle 类继承自 Shape,它有自己的成员变量 width 和 height 表示矩形的宽和高,其构造函数用于初始化这两个属性。关键的是实现的 clone 函数,通过 new Rectangle(this) 利用拷贝构造函数创建了一个新的 Rectangle 对象,这个新对象就是原对象的副本,然后返回这个副本的指针(以 Shape 类型返回,体现了多态性)。
在 main 函数中,先创建了一个原始的矩形对象 originalRect 并调用 draw 展示其信息,然后通过原型模式调用 clone 方法复制出一个新的矩形对象 clonedRect,同样调用 draw 展示,最后记得释放动态分配的内存(通过 delete 操作符),避免内存泄漏。
实际应用中,如果类的成员变量有指针等情况,可能还需要更细致地处理拷贝构造函数来确保深拷贝正确执行,避免出现意外的数据共享和修改问题。

深拷贝、浅拷贝

浅拷贝仅复制对象的引用(指针),而深拷贝会创建一个新对象,并复制对象的内容。
同一类型的对象之间可以赋值,使得两个对象的成员变量的值相同,两个对象仍然是独立的两个对象,这种情况被称为浅拷贝.
一般情况下,浅拷贝没有任何副作用,但是当类中有指针,并且指针指向动态分配的内存空间,析构函数做了动态内存释放的处理,会导致内存问题。

class MyClass {
public:int* data;MyClass(int value) {data = new int(value);}// 浅拷贝构造函数MyClass(const MyClass& other) {data = other.data; // 浅拷贝,指针复制}// 析构函数~MyClass() {delete data;}
};class MyClass {
public:int* data;MyClass(int value) {data = new int(value);}// 深拷贝构造函数MyClass(const MyClass& other) {data = new int(*(other.data)); // 深拷贝,复制对象内容}// 赋值运算符,进行深拷贝MyClass& operator=(const MyClass& other) {if (this != &other) {delete data;data = new int(*(other.data)); // 深拷贝}return *this;}// 析构函数~MyClass() {delete data;}
};

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

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

相关文章

flutter --no-color pub get 超时解决方法

新建Flutter项目后&#xff0c;运行报错&#xff0c;需要执行pub get 点击Run ‘flutter pub get’ … … … 卡着&#xff0c;不动了&#xff0c;提示超时 是因为墙的问题 解决方案&#xff1a; 添加以下环境变量 变量名: PUB_HOSTED_URL 变量值: https://pub.flutter-io.cn …

【C++】优先级队列以及仿函数

本篇我们来介绍一下优先级队列 priority_queue 。优先级队列的底层是数据结构中的堆&#xff0c;在C中它是一个容器适配器&#xff0c;这个容器适配器比之前的栈和队列更复杂。 1.priority_queue的介绍 1.1 优先级队列的底层 因为优先级队列就是堆&#xff0c;堆的底层是数组…

不需要服务器,使用netlify快速部署自己的网站

Netlify简介 1.1 Netlify的功能与特点 Netlify 是一个功能强大的静态网站托管平台&#xff0c;它不仅提供了简单的网站部署功能&#xff0c;还集成了许多现代化的开发工具和服务&#xff0c;帮助开发者更高效地构建、部署和管理网站。Netlify 的核心功能包括&#xff1a; 自动…

简单工厂模式和策略模式的异同

文章目录 简单工厂模式和策略模式的异同相同点&#xff1a;不同点&#xff1a;目的&#xff1a;结构&#xff1a; C 代码示例简单工厂模式示例&#xff08;以创建图形对象为例&#xff09;策略模式示例&#xff08;以计算价格折扣策略为例&#xff09;UML区别 简单工厂模式和策…

Unity动态读取外部图片转Texture2D,内存过大问题解决方案

问题描述 加载原始图片2.63M的图片,分辨率为3023*4032,占用内存108.5M 加载原始图片12.6 M的图片,分辨率为6000*8000,占用内存427.2M 太恐怖了吧 解决方案 1.加载完图片,等比缩放,宽高改为1024或者512以下 1024占用5.2M,512占用1.3M,相比小了很多 2.原始Texture2…

linux-----进程及基本操作

进程的基本概念 定义&#xff1a;在Linux系统中&#xff0c;进程是正在执行的一个程序实例&#xff0c;它是资源分配和调度的基本单位。每个进程都有自己独立的地址空间、数据段、代码段、栈以及一组系统资源&#xff08;如文件描述符、内存等&#xff09;。进程的组成部分&am…

ArkTs组件的学习

一. AlphabetIndexer 可以与容器组件联动用于按逻辑结构快速定位容器显示区域的组件 参数名类型必填说明arrayValueArray<string>是字母索引字符串数组&#xff0c;不可设置为空selectednumber是初始选中项索引值若超出索引值范围则取默认值0 class Lxr{tImg:Resource…

51c自动驾驶~合集42

我自己的原文哦~ https://blog.51cto.com/whaosoft/12888355 #DriveMM 六大数据集全部SOTA&#xff01;最新DriveMM&#xff1a;自动驾驶一体化多模态大模型&#xff08;美团&中山大学&#xff09; 近年来&#xff0c;视觉-语言数据和模型在自动驾驶领域引起了广泛关注…

Linux限制root 用户的远程登录(安全要求)

前言&#xff1a;现在基本用户主机都不允许使用root来操作&#xff0c;所以本文通过创建新用户&#xff0c;并限制root用户的ssh来解决这个问题 1. 创建新账户 aingo 首先&#xff0c;使用 root 账户登录系统。 sudo useradd aingo设置 aingo 账户密码&#xff1a; sudo pa…

前端学习笔记-Vue篇-04

4 Vue中的ajax 4.1 解决开发环境Ajax跨域问题 vue脚手架配置代理 配置参考 | Vue CLI方法一&#xff1a;在vue.config.js中添加如下配置: module.exports {devServer: {proxy: http://localhost:4000} } 说明: 1.优点:配置简单&#xff0c;请求资源时直接发给前端(8080)即…

【优选算法篇】位运算小课堂:从入门到精通的奇妙之旅(上篇)

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

【Linux】重启系统后开不开机(内核模块丢失问题)

问题 重启后开不开机报错如下&#xff1a; FAILED failed to start load kernel moduiles 可以看到提示module dm_mod not found 缺少了dm_mod 在内核module目录中 reboot重启可以看到这个现象&#xff1a; 可以看到重启启动磁盘&#xff0c;加载不到root 原因 dm_mod模块…

【现代服务端架构】传统服务器 对比 Serverless

在现代开发中&#xff0c;选择合适的架构是至关重要的。两种非常常见的架构模式分别是 传统服务器架构 和 Serverless。它们各有优缺点&#xff0c;适合不同的应用场景。今天&#xff0c;我就带大家一起对比这两种架构&#xff0c;看看它们的差异&#xff0c;并且帮助你选择最适…

搭建Tomcat(四)---Servlet容器

目录 引入 Servlet容器 一、优化MyTomcat ①先将MyTomcat的main函数搬过来&#xff1a; ②将getClass()函数搬过来 ③创建容器 ④连接ServletConfigMapping和MyTomcat 连接&#xff1a; ⑤完整的ServletConfigMapping和MyTomcat方法&#xff1a; a.ServletConfigMappin…

WPF DataTemplate 数据模板

DataTemplate 顾名思义&#xff0c;数据模板&#xff0c;在 wpf 中使用非常频繁。 它一般用在带有 DataTemplate 依赖属性的控件中&#xff0c;如 ContentControl、集合控件 ListBox、ItemsControl 、TabControls 等。 1. 非集合控件中使用 <UserControl.Resources>&l…

Python中exifread库使用

目录 简要介绍 库的安装 使用案例 常见问题 简要介绍 exifread 是一个用于读取图像文件 EXIF 元数据的 Python 库&#xff0c;能够提取图片的隐藏信息&#xff0c;包括经纬度、拍摄时间等信息。 库的安装 使用exifread库首先要确保已经安装 pip install exifread 使用…

clickhouse-数据库引擎

1、数据库引擎和表引擎 数据库引擎默认是Ordinary&#xff0c;在这种数据库下面的表可以是任意类型引擎。 生产环境中常用的表引擎是MergeTree系列&#xff0c;也是官方主推的引擎。 MergeTree是基础引擎&#xff0c;有主键索引、数据分区、数据副本、数据采样、删除和修改等功…

网络安全(3)_安全套接字层SSL

4. 安全套接字层 4.1 安全套接字层&#xff08;SSL&#xff09;和传输层安全&#xff08;TLS&#xff09; &#xff08;1&#xff09;SSL/TLS提供的安全服务 ①SSL服务器鉴别&#xff0c;允许用户证实服务器的身份。支持SSL的客户端通过验证来自服务器的证书&#xff0c;来鉴别…

Starfish 因子开发管理平台快速上手:如何完成策略编写与回测

DolphinDB 开发的因子开发管理平台 Starfish 围绕量化投研的因子、策略开发阶段设计&#xff0c;为用户提供了一个从数据管理、因子研究到策略回测的完整解决方案。 因子平台的回测引擎提供了多个关键的事件函数&#xff0c;涵盖策略初始化、每日盘前和盘后回调、逐笔、快照和…

排序算法(3)——归并排序、计数排序

目录 1. 归并排序 1.1 递归实现 1.2 非递归实现 1.3 归并排序特性总结 2. 计数排序 代码实现 3. 总结 1. 归并排序 基本思想&#xff1a; 归并排序&#xff08;merge sort&#xff09;是建立在归并操作上的一种有效的排序算法&#xff0c;该算法是采用分治法&#xff0…