享元模式(Flyweight Pattern)
概念:
· 属于结构型设计模式;
· 核心思想是通过共享相同的对象减少内存消耗;
UML结构:
+------------------+ | Flyweight | <<interface/abstract>> +------------------+ | +Operation(ext) | +------------------+ ▲ | +-----------------------+ | ConcreteFlyweight | +-----------------------+ | -intrinsicState | +-----------------------+ | +Operation(ext) | +-----------------------+ +-----------------------+ | FlyweightFactory | +-----------------------+ | -flyweights: dict | +-----------------------+ | +GetFlyweight(key) | +-----------------------+
代码示例:
cs/// 享元抽象类 /// </summary> public abstract class Flyweight { public abstract void Operation(string extrinsicState); } /// <summary> /// 具体享元类 /// </summary> public class ConcreteFlyweight : Flyweight { private string _intrinsicState; // 内部状态 public ConcreteFlyweight(string intrinsicState) { this._intrinsicState = intrinsicState; } /// <summary> /// 操作享元类 /// </summary> /// <param name="extrinsicState">外部状态</param> public override void Operation(string extrinsicState) { Console.WriteLine($"内部状态:{_intrinsicState}, 外部状态:{extrinsicState}"); } } /// <summary> /// 不共享的具体享元类 /// </summary> public class UnSharedConcreteFlyweight : Flyweight { private string _intrinsicState; // 内部状态 public UnSharedConcreteFlyweight(string intrinsicState) { this._intrinsicState = intrinsicState; } /// <summary> /// 操作 /// </summary> /// <param name="extrinsicState">外部状态</param> public override void Operation(string extrinsicState) { Console.WriteLine($"不共享状态:{_intrinsicState}, 外部状态:{extrinsicState}"); } } /// <summary> /// 享元工厂 /// </summary> public class FlyweightFactory { private Dictionary<string, Flyweight> _flyweightDic = new(); // 映射表 private static readonly object factorylock = new(); // 访问映射表的锁对象 /// <summary> /// 获取享元对象 /// </summary> /// <param name="key">内部状态</param> /// <returns>享元对象</returns> public Flyweight GetFlyweight(string key) { Flyweight flyweight = null; // 若存在则直接获取 if (_flyweightDic.TryGetValue(key, out flyweight) && flyweight != null) { return flyweight; } // 如果不存在或为null,则创建并添加 lock (factorylock) { if (!_flyweightDic.TryGetValue(key, out flyweight) || flyweight == null) { flyweight = new ConcreteFlyweight(key); _flyweightDic[key] = flyweight; } } return flyweight; } } /// <summary> /// 客户端 /// </summary> public class Client { public static void Main() { FlyweightFactory flyweightFactory = new FlyweightFactory(); Flyweight concreteFlyweightA = flyweightFactory.GetFlyweight("A"); Flyweight concreteFlyweightB = flyweightFactory.GetFlyweight("B"); concreteFlyweightA.Operation("A的外部状态"); concreteFlyweightB.Operation("B的外部状态"); UnSharedConcreteFlyweight unSharedConcreteFlyweight = new("不共享的对象的内部状态"); unSharedConcreteFlyweight.Operation("外部状态"); } }
特点:
优点:· 减少内存的消耗 :对象共享后,系统中不会存在大量重复对象;
· 提高性能 ;
· 便于系统扩展 ;
缺点:· 增加系统复杂性 :需要区分内部状态和外部状态,并在客户端正确管理正确的内部状态,享元工厂需要维护共享池,本身也是额外开销;
· 外部状态管理复杂 :外部状态无法被管理在享元对象中,若传入错误,很可能出现逻辑错误;
· 可能增加运行时间开销 :对于享元类的创建、查找等额外操作,带来了其他的性能开销;
· 不适合可变状态多的对象 :若对象中状态很多都不共享,使用享元模式反而本末倒置;
适用场景:
· 需要创建大量重复对象的场景;
· 对象可分为内部状态和外部状态的 ;
· 系统对性能和内存要求高的 ;
· 对象需要共享但也希望对客户端保持透明访问的 ;
举例 :
· 文本编辑器中的字符对象:
问题 :文本中大量相同字符,如果每个字符都创建一个对象,内存开销巨大;
共享对象(内部状态) :字符的字体、字号、颜色、样式等;
外部状态:字符在文档中的位置(行号、列号);
收益 :相同字符只创建一次对象,减少内存占用;
· 游戏场景中的树木、石头、建筑等静态对象:
问题:游戏地图中有成百上千棵树、石头或建筑,如果每个都独立占用内存,会很大;
共享对象(内部状态):模型、纹理、颜色;
外部状态 :位置、旋转、缩放;
收益:通过享元对象池共享模型和纹理,节省大量显存;
· 棋类游戏中的棋子对象 :
问题 :棋盘上大量棋子对象需要频繁绘制和移动,如果每个棋子都新建对象,开销大;
共享对象(内部状态) :棋子的类型(黑/白棋)、形状;
外部状态 :棋子在棋盘上的坐标;
收益:相同类型棋子只创建一次对象,移动时只更新外部状态;
【设计模式】享元模式
大飞pkz2025-09-27 9:02
相关推荐
茉莉玫瑰花茶2 小时前
C++扩展 --- 并发支持库(补充3)一只乔哇噻3 小时前
java后端工程师进修ing(研一版‖day49)枫叶丹43 小时前
【Qt开发】输入类控件(二)-> QTextEditMintYouth3 小时前
【精】C# 精确判断XML是否存在子节点JAVA学习通3 小时前
微服务项目->在线oj系统(Java-Spring)----[前端]hrrrrb4 小时前
【Python】文件处理(二)软件黑马王子4 小时前
2025Unity超详细《坦克大战3D》项目实战案例(上篇)——UI搭建并使用和数据持久化(附资源和源代码)先知后行。5 小时前
QT实现计算器掘根5 小时前
【Qt】常用控件3——显示类控件