概述
当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。
我们可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份。
定义
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。
实现
围棋接口类
/// <summary> /// 围棋接口 /// </summary> public interface IgoChessman { void Display(Coordinates coordinates); }
黑棋子类
/// <summary> /// 黑棋子 /// </summary> public class BlackIgoChessman : IgoChessman { public void Display(Coordinates coordinates) { Console.WriteLine("黑棋子,当前坐标为:x-{0},y-{1}", coordinates.x, coordinates.y); } }
白棋子类
/// <summary> /// 白棋子 /// </summary> public class WhiteIgoChessman : IgoChessman { public void Display(Coordinates coordinates) { Console.WriteLine("白棋子,当前坐标为:x-{0},y-{1}", coordinates.x, coordinates.y); } }
享元工厂类
public class IgoChessmanFactory { private static IgoChessmanFactory fac = new IgoChessmanFactory(); /// <summary> /// 共享池,存放需要被共享的黑白棋子对象 /// </summary> private Dictionary<string, IgoChessman> poor = new Dictionary<string, IgoChessman>() { { "black",new BlackIgoChessman()}, { "white",new WhiteIgoChessman()} }; private IgoChessmanFactory() { } public static IgoChessmanFactory GetInstance() { return fac; } public IgoChessman GetIgoChessman(string color) { IgoChessman igoChessman; poor.TryGetValue(color, out igoChessman); return igoChessman; } }
客户端
class Program { static void Main(string[] args) { var facroty = IgoChessmanFactory.GetInstance(); //通过工厂从享元池中复用对象 var igo1 = facroty.GetIgoChessman("black"); var igo2 = facroty.GetIgoChessman("black"); var igo3 = facroty.GetIgoChessman("black"); var igo4 = facroty.GetIgoChessman("white"); var igo5 = facroty.GetIgoChessman("white"); //注入外部不共享状态 igo1.Display(new Coordinates(0, 1)); igo2.Display(new Coordinates(0, 2)); igo3.Display(new Coordinates(0, 3)); igo4.Display(new Coordinates(0, 4)); igo5.Display(new Coordinates(0, 5)); Console.ReadLine(); } }
总结
主要优点
1、可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
2、享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
主要缺点
1、享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
2、为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。
适用场景
1、一个系统有大量相同或者相似的对象,造成内存的大量耗费。
2、 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
3、在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式