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# 设计模式(结构型模式):享元模式 (Flyweight Pattern) 在软件开发中,尤其是在处理大量对象时,我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时,通常会占用大量的内存资源,从而…...
计算机毕业设计Django+Tensorflow音乐推荐系统 音乐可视化 卷积神经网络CNN LSTM音乐情感分析 机器学习 深度学习 Flask
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
mysql 死锁案例及简略分析
准备数据 # 创一个测试表,存储引擎使用 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 重要信息 大会官网:www.ic-caice.net 大会时间:2025年1月10-12日 大会地点:中国合肥 (安徽大学磬苑…...
RIP配置实验
RIP配置实验 案例简介 天一公司下属三个分公司,属于不同的地区,三个公司之间用路由器连接,路由器名称分别为分别为 Router0、Router1、Router2,请把一公司的部门pc0,通过二公司路由器,连接三公司的部门pc1,公司之间通…...
C# 整型、浮点型 数值范围原理分析
总目录 前言 一、整型、浮点型 数值范围列表 二、什么是大小、范围 在上面的列表中,每个数据类型都有自己的Range (范围) 和 Size (大小)。 1. 范围 范围好理解,就是对应数据类型的数据范围,如 sbtyte 的数据范围是 -128~127,超…...
Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文
简介: Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户,都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具,Adobe Acrobat Pro DC 不仅…...
stable diffusion秋叶启动器安装roop插件
方法简洁明了: 第一步:下载秋叶启动器 第二步:输入网址:https://visualstudio.microsoft.com/zh-hans/downloads/,下载vs安装程序,安装开始会自动弹出如下窗口,选择2个环境:Python开…...
7-14 统计工龄
给定公司多名员工的工龄,按输入工龄顺序输出每个工龄段有多少员工。 输入格式: 给出多个整数,即每个员工的工龄,范围在[0, 50]。 输出格式: 按输入工龄顺序输出每个工龄的员工个数,格式为:“工龄:人数”。 每项占一…...
OLED的显示
一、I2C I2C时序:时钟线SCL高电平下:SDA由高变低代表启动信号,开始发送数据;SCL高电平时,数据稳定,数据可以被读走,开始进行读操作,SCL低电平时,数据发生改变࿱…...
本地测试文件解析
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(必要条件)索引库操作1.创建索引库(4步)2.删除索引库(3步)3.判断索引库是否存在(3步)4.总结:四步走 文档操作1.创建文档(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()、Right()、Substring()用法详解 1. LEFT() 函数:从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string:要操作的字符串。length&#x…...
关系分类(RC)模型和关系抽取(RE)模型的区别
目标不同 关系分类模型:对给定的实体对在给定句子中预测其关系类型。两阶段(RC) 关系抽取模型:从句子中识别出所有潜在实体对,并为其预测关系类型。一阶段(NERRE) 训练/预测阶段输入输出数据不…...
什么是索引
在数据库管理系统中,索引是一种数据结构,用于快速定位数据库表中的特定记录。索引类似于一本书的目录,可以帮助数据库引擎迅速找到所需的数据,而不必扫描整个表。 类型:常见的数据库索引类型包括B树索引、哈希索引、全…...
OJ随机链表的复制题目分析
题目内容: 138. 随机链表的复制 - 力扣(LeetCode) 分析: 这道题目,第一眼感觉非常乱,这是正常的,但是我们经过仔细分析示例明白后,其实也并不是那么难。现在让我们一起来分析分析…...
UE5材质节点Distance
Distance可以计算两个物体间的距离,可以用来做过渡效果 当相机和物体距离3000的时候,就会渐渐从蓝过渡到红色,除以500是为了平滑过渡...
OSPF - SPF算法简述
SPF全称最短路径树算法,相信学过数据结构朋友应该看起来很熟悉 在一个区域内的路由器都会产生描述自己网络连接信息的LSA,包括两种信息,有路由信息和拓扑信息,简单的来说拓扑信息就是我连着谁,路由信息就是链路的地址…...
7.UE5横板2D游戏,添加分类,创建攻击,死亡逻辑,黑板实现追击玩家行为
目录 1.将变量分类 2.创建攻击 3.应用伤害逻辑 4.死亡逻辑,停止AI行为 5.AI追击玩家,使用黑板实现 1.将变量分类 2.创建攻击 创建攻击输入为鼠标左键,并绑定映射。 攻击动画,在角色状态的枚举中添加一个新的枚举 攻击输入的…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
