亨元模式 结构型模式之六
1.定义
享元模式是一种结构型设计模式, 它允许你在消耗少量内存的情况下支持大量对象。
2.滑滑梯问题
在说明亨元模式之前,我们先看看关于滑滑梯的程序设计。小区的楼下只有三个滑滑梯,但是想玩的小朋友却非常多。怎么设计计滑滑梯资源的管理,避免小朋友使用滑滑梯的时发生冲突呢。(这里我们设定每个滑滑梯每次仅能供一个小朋友玩耍)。解决这个问题,我们就可以使用享元模式(Flyweight),它就是运用共享技术有效的支持大量细粒度的对象。
怎么理解大量细粒度的对象呢?我一开始理解亨元模式的时候其实对这个概念理解的并不清楚。就滑滑梯这个问题,大家认为大量细粒度对象是滑滑梯还是小朋友呢?如果这个问题回答的不好,那么说明你对亨元模式还是不够了解。这里我直接给出答案,大量细粒度的对象指的是滑滑梯。有朋友会很疑惑,滑滑梯我们不是设定有三个么?怎么是大量细粒度对象,哪儿来的大量。其实这个问题逻辑很简单,我们假设有一百个小朋友要玩滑滑梯,那事实上我们只要造一百个滑滑梯就好了,对么。但现实是,我们并没有那么蠢,我们让小朋友排着队轮流玩就好了。三个滑滑梯事实上是果,是采用了亨元模式的果,已经是亨元模式优化过的情况。如果没有亨元模式,那么我们确实要造一百个滑滑梯,每个小朋友专属一个。
3.实现思路
如果不对滑滑梯的资源进行管理,可能会出现这个情况:小朋友们在使用滑滑梯时,并考虑当前滑滑梯是否被使用。很可能两个小朋友同时使用一个滑滑梯,导致冲突,不符合预期。所以我们重点是要对滑滑梯的资源使用进行有效的管理,比如这时候有一个大人来维护滑滑梯的使用秩序。大人作为三个滑滑梯的管理员,小朋友们使用滑滑梯需要向他提出申请,得到准许之后才能玩。经过大人管理之后的滑滑梯使用会变成这个情况:小朋友们排队申请滑滑梯的使用权限,大人根据滑滑梯的现有使用状况,如果还有滑滑梯上没有小朋友玩耍,那么可以提供该滑滑梯给小朋友,如果滑滑梯全部被使用则小朋友申请资源失败,需要继续等待。
我们进一步假设,加入这时候小区其实存在若干个备用的充气滑滑梯,而且小区虽然有一百个小朋友,但他们并不是同时都在楼下玩的。这个时候整个系统就是一个动态的过程。只要有小朋友申请玩滑滑梯,管理员有限在现有的滑滑梯资源里找,如果有空闲的滑滑梯就会提供给当前申请的小朋友,如果没有那么就(新建资源)使用备用的充气滑滑梯。如果连备用的充气滑滑梯都用完了,这就已经触及到系统的资源上限了(内存上限),还是需要排队。
总而言之,恒元模式就是解决需要为一个小朋友定制一个滑滑梯的问题。通过共享资源池来达到相同的目的。
4.组成结构
- 抽象享元:为具体享元角色规定了必须实现的方法,而外部状态就是以参数的形式通过此方法传入。(滑滑梯)
- 具体享元:实现抽象角色规定的方法。如果存在内部状态,就负责为内在部状态提供存储空间。(社区里具体的滑滑梯)
- 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!(管理员)
- 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外部状态。 (小朋友)
内部状态,就是各个对象不会随着环境的改变而改变的可共享部分;(滑梯本身)
外部状态,指对象随环境改变而改变的不可以共享的部分。内部状态和外部状态彼此互不影响,改变其中一个并不会改变另一个的行为。(滑梯使用者)。
享元模式将享元对象的状态外部化,而读取外部状态可能使得运行时间稍微变长。
5.示例代码
#include <iostream>
#include<string>
#include<map>
using namespace std;//客户端类
class Kid
{
private:string m_name;
public:Kid(string name){m_name = name;}std::string GetName(){return m_name;}
};//抽象亨元类(滑滑梯)
class Slide
{
public:virtual ~Slide() = default;virtual void Use(Kid user) = 0;
};//具体亨元类(小区的滑滑梯)
class ConcreteSlide :public Slide
{
private:string m_id;
public:ConcreteSlide(std::string id){m_id = id;}void Use(Kid user)override{cout << "滑滑梯:" << m_id << " 小朋友:" + user.GetName() << endl;}
};//滑滑梯管理员
//如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
class SlideFactory
{
private:std::map<std::string, Slide*> flyweights;
public:~SlideFactory(){for (auto it = flyweights.begin(); it != flyweights.end(); ++it)delete it->second;}Slide* GetSlideCategory(string key){for (auto it = flyweights.begin(); it != flyweights.end(); ++it){if (it->first == key)return it->second;}Slide* slide = new ConcreteSlide(key);flyweights.insert(pair<std::string, Slide*>(key, slide));return slide;}int GetSlideCount(){return flyweights.size();}
};int main()
{SlideFactory f;Slide* fx = f.GetSlideCategory("一号滑梯");fx->Use(Kid("奇奇"));Slide* fy = f.GetSlideCategory("二号滑梯");fy->Use(Kid("天天"));Slide* fz = f.GetSlideCategory("三号滑梯");fz->Use(Kid("甜甜"));Slide* fl = f.GetSlideCategory("一号滑梯");fl->Use(Kid("嘟嘟"));Slide* fm = f.GetSlideCategory("二号滑梯");fm->Use(Kid("豆芽"));Slide* fn = f.GetSlideCategory("三号滑梯");fn->Use(Kid("年年"));cout << "得到滑滑梯总数:" << f.GetSlideCount() << endl;system("pause");return 0;
}
6.引用
C++设计模式 - 享元模式 - 知乎 (zhihu.com)
C++设计模式——享元模式 - 冰糖葫芦很乖 - 博客园 (cnblogs.com)
相关文章:
亨元模式 结构型模式之六
1.定义 享元模式是一种结构型设计模式, 它允许你在消耗少量内存的情况下支持大量对象。 2.滑滑梯问题 在说明亨元模式之前,我们先看看关于滑滑梯的程序设计。小区的楼下只有三个滑滑梯,但是想玩的小朋友却非常多。怎么设计计滑滑梯资源的管理…...
面试题: Spring中Bean的实例化和Bean的初始化有什么区别?
Spring中Bean的实例化和Bean的初始化有什么区别? 背景答案扩展知识什么是实例化什么是初始化 个人评价我的回答 背景 想换工作, 看了图灵周瑜老师的视频想记录一下, 算是学习结果的一个输出. 答案 Spring 在创建一个Bean对象时, 会先创建出一个Java对象, 会通过反射来执行…...
阻塞队列,生产者消费者模型
目标: 1. 认识与使用阻塞队列 2. 认识与实现消费者模型 目录 阻塞队列的特点 生产者消费者模型 生产者消费者模型的优点 阻塞队列实现该模型 阻塞队列的特点 1. 线程安全 2. 带有阻塞特性 (1)如果队列为空,继续出队列&a…...

【RCRL充放电时间相关计算】
一. 基础知识 L、C元件称为“惯性元件”,即电感中的电流、电容器两端的电压,都有一定的“电惯性”,不能突然变化。充放电时间,不光与L、C的容量有关,还与充/放电电路中的电阻R有关。RC电路的时间常数:τRC…...
C++ primer plus--输入、输出和文件
17 输入、输出和文件 17.1 C 输入和输出概述 C 把输入和输出看做字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插到输出流中。 缓冲区是内存中的临时存储区域,是程序与文件或其他 I/O 设备之间的桥梁。 17.2 使用…...

案例题--Web应用考点
案例题--Web应用考点 负载均衡技术微服务XML和JSON无状态和有状态真题 在选择题中没有考察过web的相关知识,主要就是在案例分析题中考察 负载均衡技术 应用层负载均衡技术 传输层负载均衡技术 就近的找到距离最近的服务器,并进行分发 使用户就近获取…...
MySQL的SQL 优化:提升数据库性能
1. 插入操作优化 1.1 使用多值插入 通常情况下,插入大量数据时,使用多值插入语句比逐行插入更高效。例如,将多个数据行打包成一个 INSERT 语句: INSERT INTO users (name, email) VALUES (Alice, aliceexample.com), (Bob, bob…...

【匠心打造】从0打造uniapp 可视化拖拽设计 c_o 第十篇
一、click one for uniapp置顶: 全部免费开源 (你商业用途也没关系,不过可以告诉我公司名或者项目名,放在官网上好看点。哈哈-_-) 二、写在之前 距离上一篇更新已经大约4个月了,公司的事情,自己的一些琐事一直没时间…...

BIT-5-操作符详解(C语言初阶学习)
1. 各种操作符的介绍。 2. 表达式求值 1. 操作符分类: 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 除了 % 操作符…...

【重拾C语言】三、分支程序设计(双分支和单分支程序设计、逻辑判断、多分支程序设计、枚举类型表示;典型例题:判断闰年和求一元二次方程根)
目录 前言 三、分支程序设计 3.1 判断成绩是否及格——双分支程序设计 3.2 成绩加上获奖信息—单分支程序设计 3.3 逻辑判断——布尔类型 3.4 获奖分等级——多分支程序设计 3.5 表示汽车种类——枚举类型 3.6 例题 3.6.1 例题——判断某个年份是否闰年 3.6.2 例题—…...

Shiro应用到Web Application
一、权限基础 a) 认证(你是谁?) 判断你(被认证者)是谁的过程。通常被认证者提供用户名和密码。 常见的认证包含如下几种: 匿名认证:允许访问资源,不做任何类型的安全检查。表单认证:访问资源之前,需要提…...
【POST请求-腾讯翻译君-爬虫案例】
原因:尝试多个在线翻译平台,由于返回数据存在加密原因(暂时不会解密),最总找到 ”腾讯翻译君“ 完成爬虫案例POST请求测试 案例测试网址 腾讯翻译 :https://fanyi.qq.com/ import requests import jsoncla…...

多卡片效果悬停效果
效果展示 页面结构 从页面的结构上看,在默认状态下毛玻璃卡片是有层次感的效果叠加在一起,并且鼠标悬停在卡片区域后,卡片整齐排列。 CSS3 知识点 transform 属性的 rotate 值运用content 属性的 attr 值运用 实现页面整体布局 <div …...

首饰饰品经营商城小程序的作用是什么
首饰如耳钉、戒指、手镯等除了高价值产品外,还有很多低价产品,市场需求客户众多,在实际经营中,商家们也会面临一些痛点。 私域话题越来越多加之线上线下同行竞争、流量匮乏等,更对商家选择自建商城经营平台。 通过【…...
华为OD机试真题【服务器能耗统计】
1、题目描述 【服务器能耗统计】 服务器有三种运行状态:空载、单任务、多任务,每个时间片的能耗的分别为1、3、4; 每个任务由起始时间片和结束时间片定义运行时间; 如果一个时间片只有一个任务需要执行,则服务器处于单任务状志; 如果一个时间片有多个任务需要执行,则服务器处于…...
ubuntu按下del却出现空格(命令行下键盘错乱)
问题: 有一天远程我的ubuntu 20.04,发现为何按 del 会产生空格后移的效果,up键也会重叠显示,首先感觉是这个远程软件有问题,于是又换了xshell,发现还是不行,只能打开积灰已久的笔记本࿰…...

Go开始:Go基本元素介绍
目录 标识符与关键字Go中的标识符Go关键字关键字示例 具名的函数常规函数代码示例 方法代码示例 高阶函数代码示例 匿名函数与Lambda表达式代码示例 闭包代码示例 具名的值变量基本数据类型复合数据类型指针类型 常量基本常量类型枚举常量常量表达式 定义类型和类型别名类型定义…...

十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418)
十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418) 12.1、漏洞原理 Ruby on Rails是一个使用 Ruby 语言写的开源 Web 应用框架,它是严格按照 MVC 结构开发的。它努力使自身保持简单,来使实际的应用开发时的代码更少,使用最少…...

【计算机视觉|人脸建模】学习从4D扫描中获取的面部形状和表情的模型
本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 标题:Learning a model of facial shape and expression from 4D scans 链接:Learning a model of facial shape and expression from 4D scans | ACM Transactions on Graphics Pe…...
【ADB】蓝牙总结
ADB 打开蓝牙关闭蓝牙打开Setting查看蓝牙地址查看蓝牙名称查看蓝牙是否开启车机蓝牙Setting配置路径wifi 打开蓝牙 adb root adb shell svc bluetooth enable 关闭蓝牙 adb root adb shell bluetooth disable 打开Setting adb shell am start -n com.android.settings/.S…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...