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

C# 设计模式(结构型模式):享元模式

C# 设计模式(结构型模式):享元模式 (Flyweight Pattern)

在软件开发中,尤其是在处理大量对象时,我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时,通常会占用大量的内存资源,从而降低程序的性能。在这种情况下,享元模式(Flyweight Pattern)能够提供一种优化方案。享元模式通过共享对象来减少内存的使用,从而提高程序的性能。

1. 享元模式的定义

享元模式是一种结构型设计模式,它通过共享对象来减少内存消耗。该模式允许我们在系统中只保存一个对象的共享实例,而不是每次都创建一个新的对象。享元模式适用于大量重复对象的场景,它通过将对象的状态分为内部状态和外部状态,来优化内存使用。

  • 内部状态:对象本身存储的状态,通常是共享的,不会改变的状态。
  • 外部状态:对象的状态依赖于上下文环境,并且可能发生变化的状态。

享元模式的核心思想是将这些重复的内部状态提取出来,避免在内存中重复存储。

2. 享元模式的结构

享元模式的结构通常包含以下几个部分:

  • Flyweight:享元类,提供共享对象的接口。
  • ConcreteFlyweight:具体享元类,存储对象的共享部分(内部状态)。
  • FlyweightFactory:享元工厂类,负责管理享元对象的创建和共享。
  • Client:客户端,使用享元对象来处理外部状态。
3. 享元模式的应用场景

享元模式适用于以下几种情况:

  • 系统中有大量重复的对象。
  • 这些对象的内部状态是共享的,外部状态是可以变化的。
  • 需要优化内存消耗,特别是对于大量类似对象的场景。
4. C# 实现享元模式

假设我们有一个场景,在一个文本编辑器中,每个字符都是一个对象。大部分字符对象可能会有相同的属性,如字体、颜色等,而这些属性不会改变。通过享元模式,我们可以将共享的部分(例如字符的字体、颜色)提取出来,只保存一个实例,避免重复创建相同的对象。

示例:文本编辑器中的享元模式
using System;
using System.Collections.Generic;// 享元类:字符
public interface ICharacter
{void Display(int x, int y);
}// 具体享元类:字母字符
public class ConcreteCharacter : ICharacter
{private string character;private string font;// 内部状态:字符内容和字体是共享的public ConcreteCharacter(string character, string font){this.character = character;this.font = font;}public void Display(int x, int y){Console.WriteLine($"Displaying character '{character}' at ({x}, {y}) with font '{font}'");}
}// 享元工厂类:字符工厂
public class CharacterFactory
{private Dictionary<string, ICharacter> characters = new Dictionary<string, ICharacter>();public ICharacter GetCharacter(string character, string font){string key = character + font;if (!characters.ContainsKey(key)){characters[key] = new ConcreteCharacter(character, font);Console.WriteLine($"Creating new character: {character} with font: {font}");}else{Console.WriteLine($"Reusing existing character: {character} with font: {font}");}return characters[key];}
}// 客户端代码
class Program
{static void Main(string[] args){CharacterFactory characterFactory = new CharacterFactory();// 客户端请求不同位置的字符ICharacter charA1 = characterFactory.GetCharacter("A", "Arial");charA1.Display(10, 20); // 显示字符AICharacter charB1 = characterFactory.GetCharacter("B", "Arial");charB1.Display(30, 40); // 显示字符BICharacter charA2 = characterFactory.GetCharacter("A", "Arial");charA2.Display(50, 60); // 再次显示字符A,复用ICharacter charA3 = characterFactory.GetCharacter("A", "Times New Roman");charA3.Display(70, 80); // 显示字符A,使用不同字体}
}
代码解析:
  • ICharacter:定义了字符对象的接口,包含 Display 方法来展示字符。
  • ConcreteCharacter:实现了 ICharacter 接口,表示具体的字符对象。它的字体和字符内容是享元的内部状态,在多个对象间共享。
  • CharacterFactory:享元工厂类,管理字符对象的创建和共享。它使用字典缓存已创建的字符对象,并在请求时返回相同对象的引用,避免重复创建。
  • 客户端代码:客户端通过 CharacterFactory 请求字符对象,并使用它们来显示字符。相同字体的字符对象会被复用,而不同字体的字符对象会创建新的实例。
运行结果:
Creating new character: A with font: Arial
Displaying character 'A' at (10, 20) with font 'Arial'
Creating new character: B with font: Arial
Displaying character 'B' at (30, 40) with font 'Arial'
Reusing existing character: A with font: Arial
Displaying character 'A' at (50, 60) with font 'Arial'
Creating new character: A with font: Times New Roman
Displaying character 'A' at (70, 80) with font 'Times New Roman'
5. 享元模式的优缺点

优点

  • 节省内存:享元模式通过共享对象来减少内存占用,特别适合大量相似对象的场景。
  • 提高性能:通过复用已有的对象,减少了创建和销毁对象的开销,提高了程序的性能。
  • 灵活的状态管理:通过将对象的内部状态和外部状态分开管理,享元模式能够灵活处理不同的状态变化。

缺点

  • 增加复杂性:享元模式的引入可能会增加系统的复杂性,特别是在管理享元对象的工厂类和对象共享策略时。
  • 可能导致对象状态管理不方便:外部状态需要由客户端来管理,可能增加一些操作上的复杂度。
6. 总结

享元模式通过共享对象来优化内存使用,特别适用于需要大量相似对象的场景。它通过将对象的状态分为内部状态和外部状态,在保证对象复用的同时,也能够灵活处理不同的外部状态。享元模式的核心目标是减少内存消耗提高程序性能,尤其是在处理大量相似对象时。

通过这个示例,我们可以看到享元模式如何有效地管理重复对象,减少不必要的内存开销。如果你在开发过程中遇到类似的性能瓶颈,可以考虑使用享元模式来优化你的系统。


相关文章:

C# 设计模式(结构型模式):享元模式

C# 设计模式&#xff08;结构型模式&#xff09;&#xff1a;享元模式 (Flyweight Pattern) 在软件开发中&#xff0c;尤其是在处理大量对象时&#xff0c;我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时&#xff0c;通常会占用大量的内存资源&#xff0c;从而…...

计算机毕业设计Django+Tensorflow音乐推荐系统 音乐可视化 卷积神经网络CNN LSTM音乐情感分析 机器学习 深度学习 Flask

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

mysql 死锁案例及简略分析

准备数据 # 创一个测试表&#xff0c;存储引擎使用 innodb create table test_lock (id int primary key auto_increment,name varchar(20),age int )engine innodb;insert into test_lock (name,age) values (ionc001,10); insert into test_lock (name,age) values (ionc00…...

第四届计算机、人工智能与控制工程

第四届计算机、人工智能与控制工程 The 4th International Conference on Computer, Artificial Intelligence and Control Engineering 重要信息 大会官网&#xff1a;www.ic-caice.net 大会时间&#xff1a;2025年1月10-12日 大会地点&#xff1a;中国合肥 (安徽大学磬苑…...

RIP配置实验

RIP配置实验 案例简介 天一公司下属三个分公司&#xff0c;属于不同的地区&#xff0c;三个公司之间用路由器连接&#xff0c;路由器名称分别为分别为 Router0、Router1、Router2&#xff0c;请把一公司的部门pc0,通过二公司路由器&#xff0c;连接三公司的部门pc1,公司之间通…...

C# 整型、浮点型 数值范围原理分析

总目录 前言 一、整型、浮点型 数值范围列表 二、什么是大小、范围 在上面的列表中&#xff0c;每个数据类型都有自己的Range (范围) 和 Size (大小)。 1. 范围 范围好理解&#xff0c;就是对应数据类型的数据范围&#xff0c;如 sbtyte 的数据范围是 -128~127&#xff0c;超…...

Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文

简介&#xff1a; Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户&#xff0c;都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具&#xff0c;Adobe Acrobat Pro DC 不仅…...

stable diffusion秋叶启动器安装roop插件

方法简洁明了&#xff1a; 第一步&#xff1a;下载秋叶启动器 第二步&#xff1a;输入网址&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/&#xff0c;下载vs安装程序&#xff0c;安装开始会自动弹出如下窗口&#xff0c;选择2个环境&#xff1a;Python开…...

7-14 统计工龄

给定公司多名员工的工龄&#xff0c;按输入工龄顺序输出每个工龄段有多少员工。 输入格式: 给出多个整数&#xff0c;即每个员工的工龄&#xff0c;范围在[0, 50]。 输出格式: 按输入工龄顺序输出每个工龄的员工个数&#xff0c;格式为&#xff1a;“工龄:人数”。 每项占一…...

OLED的显示

一、I2C I2C时序&#xff1a;时钟线SCL高电平下&#xff1a;SDA由高变低代表启动信号&#xff0c;开始发送数据&#xff1b;SCL高电平时&#xff0c;数据稳定&#xff0c;数据可以被读走&#xff0c;开始进行读操作&#xff0c;SCL低电平时&#xff0c;数据发生改变&#xff1…...

本地测试文件解析

PostMapping("/test") public void test() throws IOException {Path csvFile Paths.get("D:\\test/27.csv");//虚拟机退出时删除临时文件csvFile.toFile().deleteOnExit();List<String> list Files.readAllLines(csvFile, Charset.forName("…...

Elasticsearch JavaRestClient版

文章目录 初始化RestHighLeveClient&#xff08;必要条件&#xff09;索引库操作1.创建索引库&#xff08;4步&#xff09;2.删除索引库&#xff08;3步&#xff09;3.判断索引库是否存在&#xff08;3步&#xff09;4.总结&#xff1a;四步走 文档操作1.创建文档&#xff08;4…...

ubuntu 使用s3fs配置自动挂载对象存储

一、环境准备 1.有访问对象存储权限的AKSK 2.服务器、对象存储 二、实施步骤 sudo apt update sudo apt install s3fs echo "AK:SK" >/home/ubuntu/.passwd-s3fs ---位置自定义 chmod 600 /home/ubuntu/.passwd-s3fs ---权限必须要有 mkdir /data sudo s3fs …...

SQL字符串截取函数——Left()、Right()、Substring()用法详解

SQL字符串截取函数——Left&#xff08;&#xff09;、Right&#xff08;&#xff09;、Substring&#xff08;&#xff09;用法详解 1. LEFT() 函数&#xff1a;从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string&#xff1a;要操作的字符串。length&#x…...

关系分类(RC)模型和关系抽取(RE)模型的区别

目标不同 关系分类模型&#xff1a;对给定的实体对在给定句子中预测其关系类型。两阶段&#xff08;RC&#xff09; 关系抽取模型&#xff1a;从句子中识别出所有潜在实体对&#xff0c;并为其预测关系类型。一阶段&#xff08;NERRE&#xff09; 训练/预测阶段输入输出数据不…...

什么是索引

在数据库管理系统中&#xff0c;索引是一种数据结构&#xff0c;用于快速定位数据库表中的特定记录。索引类似于一本书的目录&#xff0c;可以帮助数据库引擎迅速找到所需的数据&#xff0c;而不必扫描整个表。 类型&#xff1a;常见的数据库索引类型包括B树索引、哈希索引、全…...

OJ随机链表的复制题目分析

题目内容&#xff1a; 138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 分析&#xff1a; 这道题目&#xff0c;第一眼感觉非常乱&#xff0c;这是正常的&#xff0c;但是我们经过仔细分析示例明白后&#xff0c;其实也并不是那么难。现在让我们一起来分析分析…...

UE5材质节点Distance

Distance可以计算两个物体间的距离&#xff0c;可以用来做过渡效果 当相机和物体距离3000的时候&#xff0c;就会渐渐从蓝过渡到红色&#xff0c;除以500是为了平滑过渡...

OSPF - SPF算法简述

SPF全称最短路径树算法&#xff0c;相信学过数据结构朋友应该看起来很熟悉  在一个区域内的路由器都会产生描述自己网络连接信息的LSA&#xff0c;包括两种信息&#xff0c;有路由信息和拓扑信息&#xff0c;简单的来说拓扑信息就是我连着谁&#xff0c;路由信息就是链路的地址…...

7.UE5横板2D游戏,添加分类,创建攻击,死亡逻辑,黑板实现追击玩家行为

目录 1.将变量分类 2.创建攻击 3.应用伤害逻辑 4.死亡逻辑&#xff0c;停止AI行为 5.AI追击玩家&#xff0c;使用黑板实现 1.将变量分类 2.创建攻击 创建攻击输入为鼠标左键&#xff0c;并绑定映射。 攻击动画&#xff0c;在角色状态的枚举中添加一个新的枚举 攻击输入的…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...