Flyweight 享元模式简介与 C# 示例【结构型6】【设计模式来了_11】
〇、简介
1、什么是享元模式?
一句话解释:
将相似或同类的对象共享同一个对象,将这些对象暂存在列表中,使用时直接取出,避免每次使用时都要新建浪费资源。
享元模式的目的是减少对象的创建,通过共享对象来提高系统的性能。享元设计模式将对象的实例分为两种:内部共享对象和外部共享对象。内部共享对象是由享元类创建的,可以被多个对象共享。外部共享对象是由客户端创建的,不能被多个对象共享。
官方意图描述:运用共享技术有效地支持大量细粒度的对象。
一个比喻:(学校的足球场和篮球馆)
首先对于学校的足球场和篮球馆有共享属性,当有足球比赛时,就对应的是足球场,有篮球比赛时,对应的就是篮球馆,不会每次比赛都去新建场馆。
2、享元模式的优缺点和适用场景
优点:
- 减少对象的创建:享元设计模式通过共享对象来减少对象的创建,这样可以减少内存占用从而提高系统的性能。
- 简化客户端代码:客户端只需要与享元接口交互,而不需要了解底层的具体实现细节,从而简化了客户端的代码。
- 提高系统的扩展性:享元设计模式通过共享对象来提高系统的扩展性,这样可以方便地添加新的共享对象。
- 降低系统的耦合度:享元模式将对象的创建和使用分离开来,使得系统的各个部分之间的耦合度降低,提高了系统的可维护性和可扩展性。
缺点:
- 增加了系统的复杂性:享元模式需要引入额外的享元工厂类和享元类,增加了系统的复杂性。
- 可能增加系统的维护成本:享元模式可能会增加系统的维护成本,因为需要考虑如何更新对象、如何维护对象、如何测试对象等问题。
- 影响系统的稳定性:当新增类型时,需要对享元工厂进行修改,可能导致系统的异常,同时也会增加额外的维护成本。
适用场景:
- 对象池:当需要频繁创建和销毁相似的对象时,可以使用享元模式将这些对象缓存在一个池中,以便重复使用。这样可以减少对象的创建和销毁成本,提高性能。
- 文字编辑器:在文字编辑器中,每个字符都可以作为一个独立的对象来表示。但对于相同的字符,我们不必为每个出现的位置都创建一个新对象,而是可以共享同一个对象实例,从而节省内存空间。
- 缓存系统:在缓存系统中,经常需要缓存大量的数据对象。通过使用享元模式,可以共享相同的数据对象,减少内存占用,并提高缓存的效率。
- 游戏开发:在游戏中,特别是大规模多人在线游戏(MMOG)中,存在大量相似的对象,如玩家、怪物、道具等。通过使用享元模式,可以共享这些相似对象之间的公共数据,并且只需存储各个对象的变化部分,从而节省内存占用。
一、通过简单的示例代码实现享元模式
如下示例代码,通过一个字典来存储类的实例,如果 key 标识的实例第二次调用时,就直接从字典中取,不再重新创建:
// 测试一下
class Program
{
static void Main(string[] args)
{
Flyweight flyweight = FlyweightFactory.GetFlyweight("Flyweight");
Flyweight flyweight1 = FlyweightFactory.GetFlyweight("Flyweight1");
Flyweight flyweight2 = FlyweightFactory.GetFlyweight("Flyweight2");
flyweight.Operation();
flyweight1.Operation();
flyweight2.Operation();
Console.ReadLine();
}
}
public class FlyweightFactory
{
private static Dictionary<string, Flyweight> flyweightDictionary = new Dictionary<string, Flyweight>();
public static Flyweight GetFlyweight(string key)
{
if (flyweightDictionary.ContainsKey(key))
{
return flyweightDictionary[key];
}
else
{
switch (key)
{
case "Flyweight1":
ConcreteFlyweight1 flyweight1 = new ConcreteFlyweight1();
flyweightDictionary[key] = flyweight1;
return flyweight1;
case "Flyweight2":
ConcreteFlyweight2 flyweight2 = new ConcreteFlyweight2();
flyweightDictionary[key] = flyweight2;
return flyweight2;
default:
Flyweight flyweight = new Flyweight();
flyweightDictionary[key] = flyweight;
return flyweight;
}
}
}
}
public class Flyweight
{
public virtual void Operation()
{
Console.WriteLine("Operation is performed by Flyweight.");
}
}
public class ConcreteFlyweight1 : Flyweight
{
public override void Operation()
{
Console.WriteLine("ConcreteFlyweight1 is performing the operation.");
}
}
public class ConcreteFlyweight2 : Flyweight
{
public override void Operation()
{
Console.WriteLine("ConcreteFlyweight2 is performing the operation.");
}
}

若后续需要添加新的享元实例ConcreteFlyweight3,就可以直接继承类Flyweight,但同时也需要在FlyweightFactory工厂类中添加对应的实例判断代码。
二、结构
根据上一章节中的示例代码,可以得结构图:

Flyweight:描述一个接口,通过这个接口 flyweight 可以接受并作用于外部状态。
ConcreteFlyweight:实现 Flyweight 接口,并为内部状态(如果有的话)增加存储空间。Concrete-Flyweight 对象是可共享的。它所存储的状态必须是内部的,即它必须独立于 ConcreteFlyweight 对象的场景。
FlyweightFactory:创建并管理flyweight 对象;确保合理地共享 flyweight。当用户请求一个 flyweight 时,FlyweightFactory 对象提供一个已创建的实例或者创建一个(如果不存在的话)。
Client:维持一个对 flyweight 的引用;计算或存储一个或多个 flyweight 的外部状态。
三、相关模式
Flyweight 享元模式通常和 Composite 组合模式结合起来,用共享叶结点的有向无环图实现一个逻辑上的层次结构。
通常,最好用 flyweight 实现 State 状态模式和Strategy 策略模式对象。
Flyweight 享元模式简介与 C# 示例【结构型6】【设计模式来了_11】的更多相关文章
- Flyweight享元模式(结构型模式)
1.面向对象的缺点 虽然OOP能很好的解决系统抽象的问题,并且在大多数的情况下,也不会损失系统的性能.但是在某些特殊的业务下,由于对象的数量太多,采用面向对象会给系统带来难以承受的内存开销.示例代码如 ...
- Flyweight 享元模式 MD
享元模式 简介 在JAVA语言中,String类型就是使用了享元模式,JAVA中的字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝,避免了在创建N多相同对象时所产生的不 ...
- Java设计模式:Flyweight(享元)模式
概念定义 享元(Flyweight)模式运用共享技术高效地支持大量细粒度对象的复用. 当系统中存在大量相似或相同的对象时,有可能会造成内存溢出等问题.享元模式尝试重用现有的同类对象,如果未找到匹配的对 ...
- 20、FlyWeight 享元模式
池化的思想 1.Flyweight享元模式 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用.由于享元模式要求能够共享的对象必 ...
- C++设计模式-Flyweight享元模式
Flyweight享元模式 作用:运用共享技术有效地支持大量细粒度的对象. 内部状态intrinsic和外部状态extrinsic: 1)Flyweight模式中,最重要的是将对象分解成intrins ...
- 设计模式之flyweight享元模式
运用共享技术支持大量细粒度对象的使用 Flyweight模式(享元) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模 ...
- 设计模式11: Flyweight 享元模式(结构型模式)
Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...
- Flyweight(享元模式)
import java.util.Hashtable; /** * 享元模式 * @author TMAC-J * 享元模式一般和工厂模式一起使用,但此处为了更好说明,只用享元模式 * 定义:享元模式 ...
- 设计模式(十二): Flyweight享元模式 -- 结构型模式
说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...
- 二十、Flyweight 享元模式
原理: 代码清单: BigChar public class BigChar { //字符名称 private char charname; //大型字符 # . \n 组成 private Stri ...
随机推荐
- Raw数据相关概念
什么是"RAW"? 维基百科的字面解释是:原始图像文件包含从数码相机.扫描器或电影胶片扫描仪的图像传感器所处理数据.RAW文件包含创建一个可视图像所必须的相机传感器数据信息. 通俗 ...
- 【技术积累】HTML+CSS+JavaScript中的基础知识【一】
HTML基础标签 <html> 定义HTML文档的根元素. <!DOCTYPE html> <html> <head> <title>My ...
- Java与PHP的区别
1.PHP暂时不支持像Java那样的JIT运行时编译的热点代码,但PHP具有opcache机制,能够将脚本对应的opcode缓存在内存中. 补充:JIT与JVM的三种执行模式:解释模式.编译模式.混合 ...
- Django CSRF cookie not set.
错误原因 由于django框架的settings.py配置了中间件,为了防止跨站请求伪造,form表单POST方式会导致出现报错 解决办法: 将'django.middleware.csrf.Csrf ...
- zabbix6.4 邮件告警配置
1.注意事项 QQ邮箱不支持zabbix6以上邮件配置,报拒绝登录 建议使用163.com网易邮箱地址 2.添加媒介 创建媒介类型-> 3.添加用户 一般情况下,无需创建用户,编辑admin即可 ...
- 使用kafka自带脚本进行压力测试
前言 kafka官方自带压力测试脚本: 消费者压力测试:kafka-consumer-perf-test.sh 生产者压力测试:kafka-producer-perf-test.sh 测试节点: 17 ...
- python处理类似json的文件
前言 有些文件长得像json的键值对格式,但又不完全是.有时需要提取出其中某些值,可以先手动处理成json文件,然后用python的json模块. 示例1:每行键值对 提取其中的caseId的值 {& ...
- .NET 8 发布的最后一个预览版Preview 7, 下个月发布RC
微软在2023年8月9日 发布了.NET 8 Preview 7[1],这是它在11月14日 RTM 之前进入发布候选阶段之前的最后预览版. 该预览版也于也与 VS 2022 v17.7 版本一起发布 ...
- Programming abstractions in C阅读笔记:p88-p90
<Programming Abstractions In C>学习第44天,p88-p90总结. 一.技术总结 1.内存分配 内存分配可以分为:static allocation.auto ...
- 操作系统实验——系统调用:获取当前进程pid和ppid
目录 一.题目介绍 二.实验思路 三.核心代码 四.遇到的问题及一些解决方法 五.参考文献 PS:博客只是提供一个简要的思路,互相学习. 一.题目介绍 显示当前进程的pid和父进程的pid,主要考察如 ...