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

11.享元模式 (Flyweight)

定义

Flyweight 模式(享元模式) 是一种结构型设计模式,它旨在通过共享对象来有效支持大量细粒度对象的复用。该模式主要通过共享细节来减少内存使用,提升性能,尤其在需要大量对象时非常有效。

基本思想:

共享对象:对象的内存资源和属性可以共享,从而减少内存消耗。
外部状态与内部状态的区分:
内部状态:在对象内部存储的属性,通常是共享的,可以被多个对象共享。
外部状态:依赖于具体的上下文环境,通常是每个对象独有的,不共享的。

Flyweight 模式的核心目标是:

  • 共享和复用:将对象的共享部分提取出来,以减少内存消耗。
  • 提高性能:通过避免重复创建大量相似的对象来提升性能。

Flyweight 模式适用于以下场景:

需要大量对象:当一个系统需要大量相似对象时,使用 Flyweight 模式可以减少内存开销。
对象细粒度重复:系统中很多对象的内部状态相同,只有外部状态不同。
资源有限的环境:在内存或者其他资源有限的环境中,Flyweight 可以有效降低资源消耗。
对象状态可分离:可以将对象的状态分为内部状态和外部状态。

常见应用场景:

图形应用:多个相同的图形(如圆形、矩形)共享相同的属性。
文字渲染:不同的字符共享相同的字体样式、大小等。

类设计

Flyweight 模式通常包括以下角色:

Flyweight(享元):定义共享对象的接口。
ConcreteFlyweight(具体享元):实现 Flyweight 接口,存储共享的状态。
FlyweightFactory(享元工厂):管理享元对象池,确保对象复用。
Client(客户端):使用享元对象,区分内部和外部状态。


#include <iostream>
#include <map>
#include <string>
using namespace std;class Font {
private:string key;  // 内部状态:唯一的字体标识符(共享部分)// 其他内部状态(例如字体样式、字体颜色等)public:Font(const string& key) : key(key) {cout << "Font created with key: " << key << endl;}void display(const string& text) {// 外部状态:文本的内容可以不同cout << "Displaying font " << key << " for text: " << text << endl;}
};class FontFactory {
private:map<string, Font*> fontPool;  // 享元池:管理字体对象(共享的内部状态)public:Font* GetFont(const string& key) {map<string, Font*>::iterator item = fontPool.find(key);if (item != fontPool.end()) {// 如果享元池中有对应的字体,直接返回cout << "Reusing existing font: " << key << endl;return item->second;} else {// 如果没有对应字体,创建新的字体对象Font* font = new Font(key);fontPool[key] = font;return font;}}void clear() {for (auto& item : fontPool) {delete item.second;}fontPool.clear();}
};int main() {FontFactory fontFactory;// 获取并显示字体Font* font1 = fontFactory.GetFont("Arial");font1->display("Hello World!");Font* font2 = fontFactory.GetFont("Arial");font2->display("Hello again!");Font* font3 = fontFactory.GetFont("Times New Roman");font3->display("New text!");// 享元池重用 "Arial" 字体Font* font4 = fontFactory.GetFont("Arial");font4->display("Reusing Arial");// 清理资源fontFactory.clear();return 0;
}

运行代码后输出如下:

Font created with key: Arial
Displaying font Arial for text: Hello World!
Reusing existing font: Arial
Displaying font Arial for text: Hello again!
Font created with key: Times New Roman
Displaying font Times New Roman for text: New text!
Reusing existing font: Arial
Displaying font Arial for text: Reusing Arial

从输出可以看到:
对于 Arial 字体,第一次调用时创建了字体对象。
第二次获取 Arial 字体时,直接复用了已经创建的对象。
对于 Times New Roman,则是新创建的字体对象。

类设计分析

  1. Font 类(享元类)
    Font 类代表一个字体对象,它有一个 key 属性作为内部状态。这是一个共享的属性。字体对象通过这个 key 来区分不同的字体样式。
    display 方法接受外部状态(例如文本内容),该外部状态每次调用时可能不同,但内部状态(如字体样式)是共享的。
  2. FontFactory 类(享元工厂)
    FontFactory 类是享元模式的核心,它负责管理所有的字体实例(通过 fontPool),并确保字体的复用。
    当请求字体对象时,GetFont 方法首先检查字体池(fontPool)中是否已有对应的字体,如果存在则返回现有实例,否则创建一个新的字体并存储到池中。
    clear 方法清理享元池中的所有对象,防止内存泄漏。
  3. 客户端
    客户端通过 FontFactory 获取字体对象,并调用 display 方法来展示文本。不同的文本内容共享相同的字体对象(即内部状态)。

总结

角色 描述
Font 享元类,存储共享的字体内部状态。
FontFactory 享元工厂,管理字体实例的池并保证字体复用。
Client 客户端,使用 FontFactory 获取字体并设置外部状态。
Flyweight 模式的优点:
节省内存:多个相同对象共享相同的内部状态,只存储一份,减少内存占用。
提高性能:通过复用相同的对象来减少对象创建的开销。
减少垃圾回收负担:复用对象减少了不必要的对象创建和销毁。
Flyweight 模式的缺点:
外部状态管理复杂:需要在客户端管理外部状态,将外部状态传递给享元对象。
实现复杂度:需要设计享元池和管理对象的共享方式,代码复杂度增加。

适用场景

游戏开发:需要大量相同的图形对象,如背景、敌人等。
文本处理:需要处理大量字符、字体、样式的渲染。
图形渲染:需要共享形状、颜色等属性的图形对象。
网络请求:不同请求使用相同的网络连接池。

总结

Flyweight 模式通过对象的共享来有效减少内存消耗,适用于需要大量相似对象的场景。它通过将对象的内部状态与外部状态区分,并只共享内部状态,从而提高了系统的效率。

相关文章:

11.享元模式 (Flyweight)

定义 Flyweight 模式&#xff08;享元模式&#xff09; 是一种结构型设计模式&#xff0c;它旨在通过共享对象来有效支持大量细粒度对象的复用。该模式主要通过共享细节来减少内存使用&#xff0c;提升性能&#xff0c;尤其在需要大量对象时非常有效。 基本思想&#xff1a; …...

Python 自学秘籍:开启编程之旅,人生苦短,我用python。

从2009年&#xff0c;用了几次python后就放弃了&#xff0c;一直用的php&#xff0c;现在人工智能时代&#xff0c;完全没php什么事情。必须搞python了&#xff0c;虽然已经40多岁了。死磕python了。让滔滔陪着你一起学python 吧。 开启新世界 在当今人工智能化的时代&#xff…...

验证工具:SVN版本控制

1-SVN概念 SVN(Subversion)是一种集中式版本控制系统,它用于文件和目录的版本管理,允许多个用户协同工作,同时追踪每个文件和目录的历史修改记录。以下是关于SVN版本控制的详细介绍: 一、SVN的基本概念 仓库(Repository):SVN的仓库是一个集中存储所有文件和目录的地…...

每日一题洛谷P5721 【深基4.例6】数字直角三角形c++

#include<iostream> using namespace std; int main() {int n;cin >> n;int t 1;for (int i 0; i < n; i) {for (int j 0; j < n - i; j) {printf("%02d",t);t;}cout << endl;}return 0; }...

React开发中箭头函数返回值陷阱的深度解析

React开发中箭头函数返回值陷阱的深度解析 一、箭头函数的隐式返回机制&#xff1a;简洁背后的规则二、块函数体中的显式返回要求&#xff1a;容易被忽视的细节三、真实场景下的案例分析案例1&#xff1a;忘记return导致组件渲染失败案例2&#xff1a;异步操作中的返回值陷阱 四…...

解决每次打开终端都需要source ~/.bashrc的问题(记录)

新服务器或者电脑通常需要设置一些环境变量&#xff0c;例如新电脑安装了Anaconda等软件&#xff0c;在配置环境变量后发现每次都需要重新source&#xff0c;非常麻烦&#xff0c;执行下面添加脚本实现一劳永逸 vim .bash_profile# .bash_profileif [ -f ~/.bashrc ]; then. ~…...

解决DeepSeek服务器繁忙问题:本地部署与优化方案

deepseek服务器崩了&#xff0c;手把手教你如何在手机端部署一个VIP通道&#xff01; 引言 随着人工智能技术的快速发展&#xff0c;DeepSeek等大语言模型的应用越来越广泛。然而&#xff0c;许多用户在使用过程中遇到了服务器繁忙、响应缓慢等问题。本文将探讨如何通过本地部…...

【后端开发】系统设计101——通信协议,数据库与缓存,架构模式,微服务架构,支付系统(36张图详解)

【后端开发】系统设计101——通信协议&#xff0c;数据库与缓存&#xff0c;架构模式&#xff0c;微服务架构&#xff0c;支付系统&#xff08;36张图&#xff09; 文章目录 1、通信协议通信协议REST API 对比 GraphQL&#xff08;前端-web服务&#xff09;grpc如何工作&#x…...

Java基础——分层解耦——IOC和DI入门

目录 三层架构 Controller Service Dao ​编辑 调用过程 面向接口编程 分层解耦 耦合 内聚 软件设计原则 控制反转 依赖注入 Bean对象 如何将类产生的对象交给IOC容器管理&#xff1f; 容器怎样才能提供依赖的bean对象呢&#xff1f; 三层架构 Controller 控制…...

武汉火影数字|VR虚拟现实:内容制作与互动科技的奇妙碰撞

VR虚拟现实是一种利用计算机技术生产三维虚拟世界的技术&#xff0c;通过头戴式显示器、手柄等设备&#xff0c;用户可以身临其境地感受虚拟世界&#xff0c;与其中的物体进行自然交互。 当内容制作遇上 VR&#xff0c;会发生什么&#xff1f; 当内容制作遇上VR&#xff0c;就像…...

一文了解性能优化的方法

背景 在应用上线后&#xff0c;用户感知较明显的&#xff0c;除了功能满足需求之外&#xff0c;再者就是程序的性能了。因此&#xff0c;在日常开发中&#xff0c;我们除了满足基本的功能之外&#xff0c;还应该考虑性能因素。关注并可以优化程序性能&#xff0c;也是体现开发能…...

SpringBoot扩展篇:@Scope和@Lazy源码解析

SpringBoot扩展篇&#xff1a;Scope和Lazy源码解析 1. 研究主题及Demo2. 注册BeanDefinition3. 初始化属性3.1 解决依赖注入3.2 创建代理 ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary3.3 代理拦截处理3.4 单例bean与原型bean创建的区别 4. …...

tkvue 入门,像写html一样写tkinter

介绍 没有官网&#xff0c;只有例子 安装 像写vue 一样写tkinter 代码 pip install tkvue作者博客 修改样式 import tkvue import tkinter.ttk as ttktkvue.configure_tk(theme"clam")class RootDialog(tkvue.Component):template """ <Top…...

c++ stl 遍历算法和查找算法

概述&#xff1a; 算法主要由头文件<algorithm> <functional> <numeric> 提供 <algorithm> 是所有 STL 头文件中最大的一个&#xff0c;提供了超过 90 个支持各种各样算法的函数&#xff0c;包括排序、合并、搜索、去重、分解、遍历、数值交换、拷贝和…...

Hackmyvm Connection

基本信息 难度&#xff1a;简单 靶机&#xff1a;192.168.194.11 kali&#xff1a;192.168.194.9 扫描 常规nmap扫描起手 nmap -sT -sV -A -T4 192.168.194.11 -p- 查看smb服务开启目录 139和445端口的smb服务直接以访客账号登录&#xff0c;无需密码验证成功。对应的ht…...

内置渲染管线和通用渲染管线的区别

内置渲染管线和通用渲染管线&#xff08;URP&#xff09;有以下区别&#xff1a; 功能特性 内置渲染管线&#xff1a;提供了一套较为基础的渲染功能&#xff0c;包括几何渲染、光照计算、阴影生成和后期处理等基本环节。但自定义选项相对有限&#xff0c;渲染次序基本是固…...

Unity 2D实战小游戏开发跳跳鸟 - 记录显示最高分

上一篇文章中我们实现了游戏的开始界面,在开始界面中有一个最高分数的UI,本文将接着实现记录最高分数以及在开始界面中显示最高分数的功能。 添加跳跳鸟死亡事件 要记录最高分,则需要在跳跳鸟死亡时去进行判断当前的分数是否是最高分,如果是最高分则进行记录,如果低于之前…...

算法随笔_40: 爬楼梯

上一篇:算法随笔_39: 最多能完成排序的块_方法2-CSDN博客 题目描述如下: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&am…...

数据结构(2)——线性表与顺序表实现

目录 前言 一、线性表 二、顺序表 2.1概念 2.2类型的选择 2.3实现 1.初始化 2.检查是否需要扩容 3.尾插 4.尾删 5.头插 6.头删 7.某一个位置添加 8.某一个位置删除 9.基于某一位置的尾插删 10.查找 11.修改 12.销毁 总结 前言 今天对顺序表进行学习&#xf…...

全面解析机器学习优化算法中的进化策略

全面解析机器学习优化算法中的进化策略 全面解析机器学习优化算法中的进化策略引言什么是进化策略?基本概念核心组件算法流程数学基础高斯扰动期望值更新与其他优化方法的比较梯度下降法(Gradient Descent, GD)遗传算法(Genetic Algorithm, GA)Python案例基本实现改进版:…...

【LeetCode】5. 贪心算法:买卖股票时机

太久没更了&#xff0c;抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…...

软件测试丨PyTorch 图像目标检测

随着人工智能和机器学习的飞速发展&#xff0c;图像目标检测技术在各个领域扮演着越来越重要的角色。无论是在安防监控、自动驾驶车辆&#xff0c;还是在医疗影像分析和智能家居中&#xff0c;图像目标检测都发挥着不可或缺的作用。今天&#xff0c;我们将深入探讨其中一种热门…...

SpringSecurity密码编码器:使用BCrypt算法加密、自定义密码编码器

1、Spring Security 密码编码器 Spring Security 作为一个功能完备的安全性框架,一方面提供用于完成加密操作的 PasswordEncoder 组件,另一方面提供一个可以在应用程序中独立使用的密码模块。 1.1 PasswordEncoder 抽象接口 在 Spring Security 中,PasswordEncoder 接口代…...

FastReport.NET控件篇之交叉表控件

认识交叉表 上面是交叉表的原型&#xff0c;关键的三个单元格。 单元格①&#xff1a;用于扩展行数据&#xff0c;譬如打印学生成绩表时&#xff0c;每个学生一行&#xff0c;那么这个地方就是以学生姓名列进行打印。 单元格②&#xff1a;用于扩展列数据&#xff0c;譬如打印…...

互联网医院开发|互联网医院成品|互联网医院系统定制

互联网医院开发设计风格需综合考量多方面因素&#xff0c;以确保其专业性、易用性与高效性。在界面设计上&#xff0c;应遵循简洁直观的原则。避免过于繁杂的布局&#xff0c;确保关键功能模块清晰呈现&#xff0c;方便用户快速定位与操作。色彩搭配要注重视觉舒适度与专业性&a…...

17.3.4 颜色矩阵

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;类似于数组。 由…...

【C++】多态详细讲解

本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态&#xff1a;主要就是我们前⾯讲的函数重载和函数模板&#xff0c;他们传不同类型的参数就可以调⽤不同的函数&#xff0c;通…...

4. k8s二进制集群之ETCD集群证书生成

安装cfssl工具配置CA证书请求文件创建CA证书创建CA证书策略配置etcd证书请求文件生成etcd证书 继续上一篇文章《负载均衡器高可用部署》下面介绍一下etcd证书生成配置。其中涉及到的ip地址和证书基本信息请替换成你自己的信息。 安装cfssl工具 下载cfssl安装包 https://github…...

Drools规则引擎初体验

前言 假设有这样一个场景&#xff0c;订单管理系统需要根据用户的消费情况&#xff0c;来为每个用户发放不同程度的优惠券&#xff0c;这个发放规则复杂且多变&#xff0c;我们该怎么办&#xff1f;在代码中写死显然是不可取的&#xff0c;规则一变就要修改代码&#xff0c;频…...

Day36【AI思考】-表达式知识体系总览

文章目录 **表达式知识体系总览**回答1&#xff1a;**表达式知识体系****一、三种表达式形式对比****二、表达式转换核心方法****1. 中缀转后缀&#xff08;重点&#xff09;****2. 中缀转前缀** **三、表达式计算方法****1. 后缀表达式计算&#xff08;栈实现&#xff09;****…...