C++ 设计模式之享元模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【简介】什么是享元模式 -- 可重复使用

        享元模式是⼀种结构型设计模式,在享元模式中,对象被设计为可共享的,可以被多个上下⽂使⽤,⽽不必在每个上下⽂中都创建新的对象。
        想要了解享元模式,就必须要区分什么是内部状态,什么是外部状态。

  • 内部状态是指那些可以被多个对象共享的状态,它存储在享元对象内部,并且对于所有享元对象都是相同的,这部分状态通常是不变的
  • 外部状态是享元对象依赖的、可能变化的部分。这部分状态不存储在享元对象内部,⽽是在使⽤享元对象时通过参数传递给对象。

        举个例⼦,图书馆中有很多相同的书籍,但每本书都可以被多个⼈借阅,图书馆⾥的书就是内部状态,⼈就是外部状态。
        再举个开发中的例⼦,假设我们在构建⼀个简单的图形编辑器,⽤户可以在画布上绘制不同类型的图形,⽽图形就是所有图形对象的内部状态(不变的),⽽图形的坐标位置就是图形对象的外部状态(变化的)。
        如果图形编辑器中有成千上万的图形对象,每个图形对象都独⽴创建并存储其内部状态,那么系统的内存占⽤可能会很⼤,在这种情况下,享元模式共享相同类型的图形对象,每种类型的图形对象只需创建⼀个共享实例,然后通过设置不同的坐标位置个性化每个对象,通过共享相同的内部状态,降低了对象的创建和内存占⽤成本。


【基本结构】

        享元模式包括以下⼏个重要⻆⾊:

  • 享元接⼝Flyweight : 所有具体享元类的共享接⼝,通常包含对外部状态的操作。
  • 具体享元类ConcreteFlyweight : 继承Flyweight 类或实现享元接⼝,包含内部状态。
  • 享元⼯⼚类FlyweightFactory : 创建并管理享元对象,当⽤户请求时,提供已创建的实例或者创建⼀个。
  • 客户端Client : 维护外部状态,在使⽤享元对象时,将外部状态传递给享元对象。


【简易实现】

         享元模式的实现通常涉及以下步骤:(以Java代码作以说明)

1. 定义享元接⼝,接受外部状态作为参数并进⾏处理。

// 步骤 1: 定义享元接⼝
interface Flyweight {// 操作外部状态void operation(String externalState);
}

2. 实现具体享元类, 存储内部状态。

// 步骤 2: 实现具体享元类
class ConcreteFlyweight implements Flyweight {private String intrinsicState; // 内部状态public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String externalState) {System.out.println("Intrinsic State: " + intrinsicState + ", External State: "+ externalState);}
}

3. 创建享元⼯⼚类,创建并管理Flyweight 对象,当⽤户请求⼀个Flyweight 时,享元⼯⼚会提供⼀个已经创建的实例或者创建⼀个。

class FlyweightFactory {private Map<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String key) {if (!flyweights.containsKey(key)) {flyweights.put(key, new ConcreteFlyweight(key));}return flyweights.get(key);}
}

4. 客户端使⽤享元模式

public class Main {public static void main(String[] args) {FlyweightFactory factory = new FlyweightFactory();// 获取或创建享元对象,并传递外部状态Flyweight flyweight1 = factory.getFlyweight("A");flyweight1.operation("External State 1");Flyweight flyweight2 = factory.getFlyweight("B");flyweight2.operation("External State 2");Flyweight flyweight3 = factory.getFlyweight("A"); // 【重复使⽤!】已存在的享元对象flyweight3.operation("External State 3");}
}

【使用场景】

        使⽤享元模式的关键在于包含⼤量相似对象,并且这些对象的内部状态可以共享。具体的应⽤场景包括⽂本编辑器,图形编辑器,游戏中的⻆⾊创建,这些对象的内部状态⽐较固定(外观,技能,形状),但是外部状态变化⽐较⼤时,可以使⽤。


【编码部分】

1. 题目描述

        在一个图形编辑器中,用户可以绘制不同类型的图形,包括圆形(CIRCLE)、矩形(RECTANGLE)、三角形(TRIANGLE)等。现在,请你实现一个图形绘制程序,要求能够共享相同类型的图形对象,以减少内存占用;

2. 输入描述

       输入包含多行,每行表示一个绘制命令。每个命令包括两部分: 图形类型(Circle、Rectangle 或 Triangle) 绘制的坐标位置(两个整数,分别表示 x 和 y);

3. 输出描述

        对于每个绘制命令,输出相应图形被绘制的位置信息。如果图形是首次绘制,输出 "drawn at",否则输出 "shared at"。

4. C++ 编码部分

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file FlyWeightMode.hpp
* @brief 享元模式
* @autor 写代码的小恐龙er
* @date 2024/01/13
*/#include <iostream>
#include <string>
#include <vector>
#include <map>using namespace std;// 形状枚举类
enum class ShapeType{CIRCLE,   // 圆形RECTANGLE,// 矩形TRIANGLE, // 三角形
};// 前置声明// 图形位置
class Position;
// 1 -- 享元接口类
class Shape;
// 2 -- 具体实现享元接口
class ConcreteShape;
// 3 -- 享元工厂
class ShapeFactory;// 图形位置
class Position
{
// 成员数据
private:int _x;int _y;// 成员函数
public:Position(){}Position(int x, int y){this->_x = x;this->_y = y;}// 成员函数获取接口int GetX(){return _x;}int GetY(){return _y;}
};// 1 -- 享元接口类
class Shape
{
// 接口函数
public:virtual void DrawShape(Position *position) = 0;
};// 2 -- 具体实现享元接口
class ConcreteShape : public Shape
{
// 成员数据
private:// 形状类型ShapeType _shapeType;// 首次绘制标志bool _firstTime = true;
// 成员函数
public:// 通过 形状类型来创建具体的对象ConcreteShape(ShapeType shapeType){this->_shapeType = shapeType;}// 设置是否首次绘制标志位void SetFirstTime(bool flag){this->_firstTime = flag;}// 重载基类的接口函数void DrawShape(Position *position){string outStr = "";switch(_shapeType){case ShapeType::CIRCLE:outStr = "CIRCLE";break;case ShapeType::RECTANGLE:outStr = "RECTANGLE";break;case ShapeType::TRIANGLE:outStr = "TRIANGLE";break;}if(_firstTime) outStr += " drawn at (";else outStr += " shared at (";std::cout << outStr << (position->GetX()) << ", " << (position->GetY()) << ")" << endl;}
};// 3 -- 享元工厂
class ShapeFactory
{
// 成员数据
private:// 包含可扩展的享元类std::map<ShapeType, Shape*> _shapesMap;// 成员函数
public:Shape* GetShape(ShapeType type){std::map<ShapeType, Shape*>::iterator pos = _shapesMap.find(type);if(pos == _shapesMap.end()){// 如果在map中找不到具体的形状实现类 则新建_shapesMap.insert(make_pair(type, new ConcreteShape(type)));}// 返回 具体的形状实现类return _shapesMap[type];}
};int main()
{// 形状类型 string type;// x yint x = 0;int y = 0;// 新建位置类Position *position = nullptr;// 新建享元工厂类ShapeFactory *shapeFactory = new ShapeFactory();while(std::cin >> type >> x >> y){// 形状类型ShapeType shapeType;if(type == "CIRCLE"){shapeType = static_cast<ShapeType>(0);}else if(type == "RECTANGLE"){shapeType = static_cast<ShapeType>(1);}else if(type == "TRIANGLE"){shapeType = static_cast<ShapeType>(2);}// 位置类position = new Position(x, y);// 具体的享元实现类Shape *shape = shapeFactory->GetShape(shapeType);// 先进行绘制操作shape->DrawShape(position);// 通过 dynamic_cast 向下类型转换ConcreteShape *concreteShape = dynamic_cast<ConcreteShape *> (shape);if(concreteShape == nullptr) return 0;// 再将该类型的标志位置为falseconcreteShape->SetFirstTime(false);}// 析构if(position != nullptr){delete position;position = nullptr;}delete shapeFactory;shapeFactory = nullptr;return 0;
}


......

To be continued.

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

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

相关文章

我记不住的那些位操作bitwise(一)

背景&#xff1a; 最近在看底层的一些知识内容&#xff0c;其中有一些位操作&#xff0c;所以想复习并记录一下。 一、或 或&#xff1a; 0 | 1 1 及 1 | 1 1 但是无法区分这两种情况(1. 一个是false&#xff0c;另一个是true&#xff1b; 2. 这两个都是true) 在C语…

PDF控件Spire.PDF for .NET【安全】演示:更改 PDF 文档的安全权限

当您使用密码保护 PDF 文档时&#xff0c;您可以选择指定一组权限。权限决定用户如何与文件交互。例如&#xff0c;您可以对文档应用权限以禁止用户打印或使用剪切和粘贴操作。本文演示如何在C# 和 VB.NET中使用Spire.PDF for .NET更改 PDF 文档的安全权限。 Spire.PDF for .N…

HTML5 article标签,<time>...</time>标签和pubdate属性的运用

1、<article>...</article>标签的运用 article标签代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。它可以是一篇博客或报竟杂志中的文章、一篇论坛帖子、一段用户评论或一个独立的插件&#xff0c;或者其他任何独立的内容。把文章正文放在h…

新喜报,新希望!英码科技荣登“2023年广州拟上市领头羊TOP50企业榜单”

近日&#xff0c;广州市资本市场融资对接服务平台启动仪式暨2023年拟上市企业“领头羊”评选总结活动成功举办。活动现场发布了2023年广州“拟上市领头羊TOP 50 企业榜单”、“最受资本关注TOP10榜单”、“最强科创TOP10榜单”、“最具成长TOP10榜单”并为企业颁发牌匾&#xf…

HCIA 网络基础:

应用层 抽象语言-->编码 表示层 编码-->二进制 会话层 建立会话&#xff0c;提供绘画地址。 应用于程序内部进行区分&#xff0c;没有统一标准 上三层主要是软件层面&#xff08;应用 程序处理数据&#xff09; 下四层主要负责数据传输 传输层 端口号 分段 &#xff…

Ubuntu开机自动挂载硬盘

前言&#xff1a; 因为我的电脑是WIN10 Ubuntu18.04双系统&#xff0c;且两个系统都装在C盘上&#xff0c;而D盘作为数据和代码存储盘&#xff0c;经常会开机就被访问&#xff0c;例如上一次关机前用VS Code访问D盘代码&#xff0c;然后下一次开机的时候打开VSCode发现打不开…

在window宿主机访问WSL2内部署的服务

目录 在window宿主机访问 WSL2 内部署的服务&#xff08;其他&#xff09;在 WSL2 内查看 windows&#xff08;宿主机&#xff09;的IP地址 windows内置了Linux系统&#xff08;WSL&#xff09;。 在window宿主机访问 WSL2 内部署的服务 在WSL下部署的项目&#xff0c;比如端口…

智能分析网关V4基于AI视频智能分析技术的周界安全防范方案

一、背景分析 随着科技的不断进步&#xff0c;AI视频智能检测技术已经成为周界安全防范的一种重要手段。A智能分析网关V4基于深度学习和计算机视觉技术&#xff0c;可以通过多种AI周界防范算法&#xff0c;实时、精准地监测人员入侵行为&#xff0c;及时发现异常情况并发出警报…

text expressing

文章目录 前言文本表示1文本特征概念介绍2 文本特征选择方法3 文本表示方法 text expressing3.1 One Hot(独热)编码3.2 TF-IDF 模型3.3 Word2Vec 参考链接&#xff1a; 前言 文本是一种非结构化的数据信息&#xff0c;是不可以直接被计算的。 文本表示的作用就是将这些非结构…

powershell的help

打开win10 的powershell窗口&#xff0c;输入help命令&#xff0c;可以得到如下说明&#xff1a; 有了help系统&#xff0c;可以方便地了解关于powershell的详细说明。

文献阅读(速读):Automating Deep Neural Network Model Selection for Edge Inference

目录 论文简介动机&#xff1a;为什么作者想要解决这个问题&#xff1f;贡献&#xff1a;作者在这篇论文中完成了什么工作(创新点)&#xff1f;规划&#xff1a;他们如何完成工作&#xff1f;自己的看法(作者如何得到的创新思路) 论文简介 作者 Bingqian Lu、Jianyi Yang、Lydi…

cesium设置近地天空盒 天空会倾斜

上篇文章讲解了如何设置近地天空盒&#xff0c;效果出来了还是发现天空是斜的 https://blog.csdn.net/m0_63701303/article/details/135618244 效果&#xff1a; 这里需要修改Cesium.skyBox的代码&#xff0c;代码如下直接全部复制组件内调用即可 skybox_nearground.js&…

分布式光伏运维平台在提高光伏电站发电效率解决方案

摘要&#xff1a;伴随着能源危机和环境恶化问题的日益加重&#xff0c;科技工作者进一步加大对新能源的开发和利用。太阳能光伏发电作为新型清洁能源的主力军&#xff0c;在实际生产生活中得到了广泛的应用。然而&#xff0c;光伏发电效率偏低&#xff0c;成为制约光伏发电发展…

机器学习算法实战案例:LSTM实现单变量滚动风电预测

文章目录 1 数据处理1.1 数据集简介1.2 数据集处理 2 模型训练与预测2.1 模型训练2.2 模型滚动预测2.3 结果可视化 答疑&技术交流机器学习算法实战案例系列 1 数据处理 1.1 数据集简介 实验数据集采用数据集5&#xff1a;风电机组运行数据集&#xff0c;包括风速、风向、…

webpack打包可视化分析工具:webpack-bundle-analyzer

在对webpack项目进行优化的时候,可以使用webpack-bundle-analyzer这个可视化插件来快速分析我们包的结构,能快速定位需要优化的地方,对开发者非常友好 下载安装 下载依赖包 npm i webpack-bundle-analyzer 使用 const BundleAnalyzerPlugin require(webpack-bundle-analy…

qt.qpa.plugin: Could not find the Qt platform plugin “windows“ in ““

系统环境&#xff1a;Win10家庭中文版 Qt : 5.12.9 链接了一些64位的第三方库&#xff0c;程序编译完运行后出现 qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "" 弹窗如下&#xff1a; 网上搜了一些都是关于pyQt的&#xff0c…

【实战记录】 vagrant+virtualbox+docker 轻松用虚拟机集成组件

用途 最近要学一大堆组件&#xff0c;不想直接安装本机上&#xff0c;然后gpt说&#xff1a;你可以用vagrant起个虚拟机&#xff08;然后docker拉取各种组件的镜像&#xff09;&#xff1b;或者k8s 实战的整体思路 首先安装virtualbox和vagrant。然后cmd依次键入三条命令 安…

旧衣回收小程序搭建:降低企业成本,提高回收效率!

在人们环保意识提升下&#xff0c;旧衣回收行业受到了大众的关注&#xff0c;同时旧衣回收具有门槛低、利润大的优势。在我国&#xff0c;回收行业不仅帮助普通人就业获利&#xff0c;还对环保做出了较大贡献。因此&#xff0c;旧衣回收行业成为了当下的热门商业模式&#xff0…

时尚女童冲锋衣外套

上身时尚又好看的外套 日常穿着或者出行游玩 应对早晚温差&#xff0c;兼具时尚和功能 保暖也可以很轻盈 率性闲适的洒脱范 版型百搭好穿 下摆有橡筋收紧更加保暖了 简直就是一件实用与时尚并存的时尚单品

Swift爬虫程序采集招聘信息代码示例

今天我将用Swift写一个爬虫程序&#xff0c;主要是爬取招聘信息网站得。我们知道Selenops是一个简单的Swift Web爬虫工具&#xff0c;可以用于爬取网页内容。您可以使用Selenops的三种方式之一来进行爬虫操作&#xff1a;Swift游乐场、Swift脚本或马拉松脚本SwiftUI是一种用于构…