12_享元模式
享元模式是一种结构型设计模式,它通过共享细粒度的对象来最大限度地减少内存使用和对象创建的数量。享元模式通过将共享对象的状态外部化,使得对象可以共享,并提供了一个工厂类来管理共享对象的创建和获取。
享元模式有五个主要角色:
-
享元接口(Flyweight):定义了共享对象的接口,包含了需要外部化的状态的方法。
-
具体享元类(Concrete Flyweight):实现了享元接口,并包含内部状态和外部状态。内部状态是可以共享的,而外部状态是不可共享的。
-
享元工厂类(Flyweight Factory):用于创建和管理享元对象。它维护了一个享元对象的池,用于存储已创建的享元对象。
-
客户端(Client):通过享元工厂类来获取共享对象,并调用共享对象的方法。客户端可以提供外部状态给享元对象。
-
非共享具体享元类(Unshared Concrete Flyweight):不可共享的具体享元类,它不实现享元接口。
享元模式的工作原理如下:
-
共享对象的状态被外部化,存储在享元对象内部或外部。
-
客户端通过享元工厂类获取共享对象,如果对象已存在,则直接返回;如果对象不存在,则创建新的共享对象并加入享元对象池。
-
客户端调用共享对象的方法,并传入外部状态。
享元模式的优点包括:
-
可以减少内存使用和对象创建的数量,提高系统性能。
-
可以共享细粒度的对象,提高系统的复用性。
-
可以通过外部化对象状态,使得对象可以共享。
享元模式适用于以下场景:
-
当需要创建大量相似的对象,并且对象的某些状态可以外部化时,可以使用享元模式。
-
当需要共享对象以减少内存使用时,可以使用享元模式。
总结而言,享元模式通过共享细粒度的对象来减少内存使用和对象创建的数量。它通过外部化对象状态和共享对象的管理来提高系统的性能和复用性。
案例:
对于围棋,颜色是内部状态,位置是外部状态
Flyweight
/// <summary> /// 抽象享元角色 /// 定义内部状态和外部状态的接口或实现 /// </summary> public abstract class Piece { protected string color = string.Empty;//不可共享的享元角色 public abstract void SetColor();//设置内部状态 public void Display(Point point) { SetColor(); Console.WriteLine($"我的颜色是:{color},我的位置:(x,y)=({point.X},{point.Y})"); } }
Concrete Flyweight
/// <summary> /// 具体享元角色 -> 黑棋子 /// </summary> public class BlackPiece : Piece { public override void SetColor() { color = "黑色棋子"; } }
public class WhitePiece : Piece { public override void SetColor() { color = "白色棋子"; } }
Flyweight Factory
public class PieceFactory { //防止实例化,只允许通过静态类获取唯一实例 private PieceFactory() { } private static readonly PieceFactory instance = new PieceFactory(); public static PieceFactory Instance=>instance; public Hashtable hashtable { get; set; } = new Hashtable();//存储享元对象 public Piece GetPiece(string key) { if(hashtable.ContainsKey(key)) { return (Piece)hashtable[key]; //有对象就直接返回对象 } if (key == "黑") { Piece piece = new BlackPiece(); hashtable.Add(key, piece); return piece; } else if (key == "白") { Piece piece = new WhitePiece(); hashtable.Add(key, piece); return piece; } else { return null; } } }
Client
internal class Client { public void Start() { PieceFactory factory = PieceFactory.Instance; Piece piece1 = factory.GetPiece("黑"); Piece piece2 = factory.GetPiece("黑"); Piece piece3 = factory.GetPiece("白"); Piece piece4 = factory.GetPiece("白"); Piece piece5 = factory.GetPiece("白"); piece1.Display(new System.Drawing.Point(10, 200)); piece2.Display(new System.Drawing.Point(54, 87)); piece3.Display(new System.Drawing.Point(66, 77)); piece4.Display(new System.Drawing.Point(88, 99)); piece5.Display(new System.Drawing.Point(139, 199)); Console.WriteLine($"{piece1 == piece2}"); Console.WriteLine($"{piece3 == piece4}"); Console.WriteLine($"{piece4 == piece5}"); Console.WriteLine($"{piece1 == piece3}"); Console.WriteLine($"hashtable中元素数量:{factory.hashtable.Count}"); } }
调用
static void Main(string[] args) { new Client().Start(); Console.ReadKey(); }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)