一、产生背景
享元模式:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
之前讲到的单例模式,一个类只有一个唯一的对象,也就是说,不管new多少次,只需要创建这个类的一个对象,如果不采用单例模式,每new一次,就会创建一个对象,便会产生大量重复的对象,而这些对象要消耗很大的资源的时候,是会产生资源互抢的延迟的。这个时候享元模式就能帮忙解决这类的问题。
二、一般做法
享元模式就是把部分和整体的关系用树形结构来表示,从而使客户端能够把一个个的部分对象和由它们组合起来的整体对象采用同样的方式来对待。享元模式主要由3部分组成:享元类,具体的享元类,享元工厂类。
三、实例
抽象享元类
/// <summary> /// 抽象享元类,提供具体享元类具有的方法 /// </summary> public abstract class Flyweight { public abstract void Operation(); }
具体享元类
/// <summary> /// 具体的享元对象 /// </summary> public class ConcreteFlyweight : Flyweight { private string intrinsicstate; // 构造函数 public ConcreteFlyweight(string innerState) { this.intrinsicstate = innerState; } /// <summary> /// 享元类的实例方法 /// </summary> /// <param name="extrinsicstate">外部状态</param> public override void Operation() { Console.WriteLine("调用了具体的对象: {0}", intrinsicstate); } }
享元工厂
/// <summary> /// 享元工厂,负责创建和管理享元对象 /// </summary> public class FlyweightFactory { public List<Flyweight> flyweights = new List<Flyweight>(); public FlyweightFactory() { flyweights.Add(new ConcreteFlyweight("第一个对象")); flyweights.Add(new ConcreteFlyweight("第二个对象")); flyweights.Add(new ConcreteFlyweight("第三个对象")); } public Flyweight GetFlyweight(int key) { Flyweight flyweight; if (key >= flyweights.Count) { Console.WriteLine("驻留池中不存在对象" + (key + 1)); flyweight = new ConcreteFlyweight("第" + (key + 1) + "个对象"); } else { flyweight = flyweights[key]; } return flyweight; } }
客户端调用
static void Main(string[] args) { // 初始化享元工厂 FlyweightFactory factory = new FlyweightFactory(); // 判断是否已经创建了对象1,如果已经创建就直接使用创建的对象 Flyweight fa = factory.GetFlyweight(0); if (fa != null) { // 把外部状态作为享元对象的方法调用参数 fa.Operation(); } // 判断是否已经创建了字母B Flyweight fb = factory.GetFlyweight(1); if (fb != null) { fb.Operation(); } // 判断是否已经创建了字母C Flyweight fc = factory.GetFlyweight(2); if (fc != null) { fc.Operation(); } // 判断是否已经创建了字母D Flyweight fd = factory.GetFlyweight(3); if (fd != null) { fd.Operation(); } else { Console.WriteLine("驻留池中不存在对象4"); // 这时候就需要创建一个对象并放入驻留池中 ConcreteFlyweight d = new ConcreteFlyweight("第四个对象"); factory.flyweights.Add(d); } Console.Read(); }
四、设计模式分析
缺点:
一、
为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑更复杂,使系统复杂化。
二、
享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。