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

【设计模式--原型模式(Prototype Pattern)

一、什么是原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,它的主要目的是通过复制现有对象来创建新的对象,而无需显式地使用构造函数或工厂方法。这种模式允许我们创建一个可定制的原型对象,然后通过复制它来创建新的对象,从而避免了重复构建相似的对象。

在原型模式中,通常有以下几个核心角色:

  1. 原型(Prototype):定义了一个克隆自己的接口,它是需要复制的对象的抽象表示。
  2. 具体原型(Concrete Prototype):实现了原型接口,实现了克隆自己的方法。
  3. 客户端(Client):负责创建新对象,通过克隆已有的原型来获得新对象的副本。

原型模式的优点包括:

  • 减少了对象的创建成本:通过克隆已有对象,避免了重新构建相似对象的成本。
  • 提高了性能:克隆比创建对象更高效,特别是在初始化成本高的情况下。
  • 隐藏了对象的创建细节:客户端不需要知道如何创建对象,只需通过克隆获得所需的对象。

然而,原型模式也有一些缺点:

  • 如果对象的构造函数有副作用,那么克隆可能会导致不一致的行为。
  • 如果对象层次较深,需要逐层克隆,可能会变得比较复杂。
  • 在某些语言或环境中,克隆对象可能需要编写较多的代码。

总之,原型模式适用于需要创建相似对象或对象层次的场景,它提供了一种更高效、灵活的对象创建方式。

二、原型模式的代码样例

以下是一个使用C++实现原型模式的简单示例:

#include <iostream>
#include <string>
#include <unordered_map>// 原型抽象类
class Prototype {
public:virtual Prototype* clone() const = 0;virtual void display() const = 0;
};// 具体原型类A
class ConcretePrototypeA : public Prototype {
public:ConcretePrototypeA(int value) : value(value) {}Prototype* clone() const override {return new ConcretePrototypeA(value);}void display() const override {std::cout << "ConcretePrototypeA with value: " << value << std::endl;}private:int value;
};// 具体原型类B
class ConcretePrototypeB : public Prototype {
public:ConcretePrototypeB(const std::string& name) : name(name) {}Prototype* clone() const override {return new ConcretePrototypeB(name);}void display() const override {std::cout << "ConcretePrototypeB with name: " << name << std::endl;}private:std::string name;
};// 原型管理器
class PrototypeManager {
public:void registerPrototype(const std::string& key, Prototype* prototype) {prototypes[key] = prototype;}Prototype* getPrototype(const std::string& key) {if (prototypes.find(key) != prototypes.end()) {return prototypes[key]->clone();}return nullptr;}private:std::unordered_map<std::string, Prototype*> prototypes;
};int main() {PrototypeManager manager;manager.registerPrototype("prototypeA", new ConcretePrototypeA(100));manager.registerPrototype("prototypeB", new ConcretePrototypeB("PrototypeB"));Prototype* clonedA = manager.getPrototype("prototypeA");if (clonedA) {clonedA->display();delete clonedA;}Prototype* clonedB = manager.getPrototype("prototypeB");if (clonedB) {clonedB->display();delete clonedB;}return 0;
}

在这个示例中,我们定义了一个原型抽象类 Prototype,然后有两个具体的原型类 ConcretePrototypeA 和 ConcretePrototypeB,它们都实现了克隆自己的方法。原型管理器 PrototypeManager 用于管理不同类型的原型对象。

通过原型模式,我们可以注册不同的原型对象,并在需要时通过原型管理器创建它们的克隆,从而实现了对象的复制和创建。这种方式可以避免重复构建相似的对象,提高了效率。

三、使用原型模式需要注意的问题

在使用原型模式时,有几个注意事项需要考虑:

  1. 深克隆与浅克隆:原型模式涉及克隆对象,而克隆可以分为深克隆和浅克隆。浅克隆只复制对象的值和指针,而不复制指针指向的对象。深克隆会递归地复制对象及其关联的所有对象。在确定克隆的方式时,需要考虑对象间的关系和内存管理。
  2. 构造函数和初始化:克隆对象不会调用构造函数,它是通过复制现有对象的内部状态来创建新对象。因此,如果在构造函数中进行了某些初始化操作,克隆对象可能会缺少这些初始化。需要确保对象的状态在克隆后正确。
  3. 单例模式和原型模式的结合:如果一个类同时实现了单例模式和原型模式,就需要特别小心。单例模式要求一个类只有一个实例,而原型模式要求创建新对象。在这种情况下,需要权衡是否要同时支持这两种模式。
  4. 对象图的复杂性:如果对象之间有复杂的关联关系,如循环引用等,克隆对象可能会导致对象图的复制变得复杂。需要仔细考虑对象之间的关系,以及克隆操作的顺序。
  5. 性能开销:深克隆可能涉及递归复制对象的所有关联对象,这可能导致性能开销较大。在性能敏感的情况下,需要权衡是否使用原型模式。

总的来说,原型模式在需要创建相似对象且效率要求较高的场景下非常有用。然而,在使用时需要注意克隆的方式、构造函数、对象关系等细节,以确保正确性和可维护性。

在这里插入图片描述

相关文章:

【设计模式--原型模式(Prototype Pattern)

一、什么是原型模式 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它的主要目的是通过复制现有对象来创建新的对象&#xff0c;而无需显式地使用构造函数或工厂方法。这种模式允许我们创建一个可定制的原型对象&#xff0c;然后通过复制…...

初识 Redis

初识 Redis 1 认识NoSQL1.1 结构化与非结构化1.2 关联和非关联1.3 查询方式1.4. 事务1.5 总结 2 Redis 概述2.1 应用场景2.2 特性 3 Resis 全局命令4 Redis 基本数据类型4.1 String4.1.1 常用命令4.1.2 命令的时间复杂度4.1.3 使用场景 4.2 Hash4.2.1 常用命令4.2.2 命令的时间…...

php灵异事件,啥都没干数据变了?

这篇文章也可以在我的博客查看 搞WordPress&#xff0c;难免跟php打交道 然而这弱类型语言实在坑有点多 这不今儿又踩了个大坑直接时间-1&#x1f605; 问题 话不多说直接上代码 <?php $items [1,2];foreach ($items as &$item) {/*empty loop*/} print_r($items)…...

【ffmpeg】基于需要使用videocapture的opencv编译配置(C++)

目录 配置简介ffmpeg源码编译方法记录gstreamer命令行安装方法opencv的编译项记录 配置简介 opencv使用videocapture读取视频流时&#xff0c;需要借助底层的ffmpeg库。如果不能正确编译&#xff0c;会报错&#xff0c;现记录正确编译配置方法。 ffmpeg源码编译方法记录 ope…...

Redisson分布式锁 原理源码 分析

# 基于setnx实现的分布式锁存在的问题&#xff1a; # 为了解决上面的问题&#xff0c;可以用Redisson # Redisson入门 # Redisson可重入锁原理 获取锁的Lua脚本&#xff1a; 释放锁的Lua脚本&#xff1a; # 锁重试原理分析 tryLock&#xff08;&#xff09;底层代码分析 tim…...

Cocos独立游戏开发框架中的事件管理器

引言 本系列是《8年主程手把手打造Cocos独立游戏开发框架》&#xff0c;欢迎大家关注分享收藏订阅。在独立游戏开发中&#xff0c;事件管理器是一个不可或缺的组件。它为开发者提供了一种灵活的方式来处理游戏内部各种状态变化和用户交互&#xff0c;实现模块之间的解耦和通信…...

keepalived+haproxy 搭建高可用高负载高性能rabbitmq集群

一、环境准备 1. 我这里准备了三台centos7 虚拟机 主机名主机地址软件node-01192.168.157.133rabbitmq、erlang、haproxy、keepalivednode-02192.168.157.134rabbitmq、erlang、haproxy、keepalivednode-03192.168.157.135rabbitmq、erlang 2. 关闭三台机器的防火墙 # 关闭…...

网络安全(黑客)零基础自学

网络安全是什么&#xff1f; 网络安全&#xff0c;顾名思义&#xff0c;网络上的信息安全。 随着信息技术的飞速发展和网络边界的逐渐模糊&#xff0c;关键信息基础设施、重要数据和个人隐私都面临新的威胁和风险。 网络安全工程师要做的&#xff0c;就是保护网络上的信息安…...

如何把本地项目上传github

一、在gitHub上创建新项目 【1】点击添加&#xff08;&#xff09;-->New repository 【2】填写新项目的配置项 Repository name&#xff1a;项目名称 Description &#xff1a;项目的描述 Choose a license&#xff1a;license 【3】点击确定&#xff0c;项目已在githu…...

跳跃游戏【贪心算法】

跳跃游戏 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。在这里插入图片…...

vue2+element-ui 实现下拉框滚动加载

一、自定义滚动指令。 VUE.directive( el-select-loadmore: { bind(el, binding) { const SELECTWRAP_DOM el.querySelector(.el-select-dropdown .el-select-dropdown__wrap) SELECTWRAP_DOM.addEventListener(scroll, function () { /*…...

探索AIGC人工智能(Midjourney篇)(二)

文章目录 利用Midjourney进行LOGO设计 用ChatGPT和Midjourney的AI绘画&#xff0c;制作儿童绘本故事 探索Midjourney换脸艺术 添加InsightFaceSwap机器人 Midjourney打造专属动漫头像 ChatGPT Midjourney画一幅水墨画 Midjourney包装设计之美 Midjourney24节气海报插画…...

01-Flask-简介及环境准备

Flask-简介及环境准备 前言简介特点Flask 与 Django 的比较环境准备 前言 本篇来介绍下Python的web框架–Flask。 简介 Flask 是一个轻量级的 Web 框架&#xff0c;使用 Python 语言编写&#xff0c;较其他同类型框架更为灵活、轻便且容易上手&#xff0c;小型团队在短时间内…...

【Git游戏】远程分支

origin/<branch> 远程分支在本地以 origin/<branch>格式存在&#xff0c;他指向上次和远程分支通过时的记录 git checkout origin/<branch> 会出现HEAD分离的情况 与远程通讯 git fetch —— 从远端获取数据&#xff08;实际上将本地仓库中的远程分支更新…...

Day07-ElementUI

Day02-ElementUI 一 菜单设计 1 静态菜单 a 在components文件夹中新建一个组件Menu.vue <template><div class="menu-wrap"><el-menuclass="el-menu-vertical-demo"background-color="#031627"text-color="#fff"ac…...

【Go 基础篇】Go语言中的defer和recover:优雅处理错误

Go语言以其简洁、高效和强大的特性受到了开发者的热烈欢迎。在错误处理方面&#xff0c;Go语言提供了一种优雅的机制&#xff0c;即通过defer和recover组合来处理恐慌&#xff08;panic&#xff09;错误。本文将详细介绍Go语言中的defer和recover机制&#xff0c;探讨其工作原理…...

4.15 TCP Keepalive 和 HTTP Keep-Alive 是一个东西吗?

目录 HTTP 的 Keep-Alive TCP 的 Keepalive 总结&#xff1a; HTTP的Keep-Alive&#xff0c;是应用层&#xff08;用户态&#xff09;实现的&#xff0c;称为HTTP长连接&#xff1b; TCP的Keepalive&#xff0c;是由TCP层&#xff08;内核态&#xff09;实现的&#xff0c;…...

如何在VSCode中将html文件打开到浏览器

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

2022年03月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;拦截导弹 某国为了防御敌国的导弹袭击&#xff0c; 发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷&#xff1a; 虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 某天&#xff0c; 雷达捕捉到敌国的…...

五公里场地训练笔记(完整版)

由于考研和口罩等原因&#xff0c;停跑了比较长的时间。中长距离就是这样&#xff0c;修为尽失&#xff0c;大概是要从头开始了&#xff0c;不过还是要乐观的面对&#xff0c;CHEER UP&#xff01; 翻看咕咚软件&#xff0c;以前的PB是21&#xff1a;12&#xff0c;在2017年9月…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...