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.创建攻击 创建攻击输入为鼠标左键,并绑定映射。 攻击动画,在角色状态的枚举中添加一个新的枚举 攻击输入的…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
