一.概述:享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
二.两个状态:
内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的
外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。
三.享元模式的实现:
在编辑器中可能出现很多字符,使用享元模式去实现这个编辑器的,会把每个字做成一个享元对象。享元对象的内部状态就是这个字面,而字母在文本中的位置和字体风格等其他信息就是它的外部状态。下面就以这个例子来实现下享元模式,具体实现代码如下:
/// <summary> /// 抽象享元类,提供具体享元类具有的方法 /// </summary> public abstract class Flyweight { public abstract void Operation(int extrinsicstate); }
/// <summary> /// 享元工厂,负责创建和管理享元对象 /// </summary> public class FlyweightFactory { public Hashtable flyweighrs = new Hashtable(); public FlyweightFactory() { flyweighrs.Add("A",new ConcreteFlyweight("A")); flyweighrs.Add("B",new ConcreteFlyweight("B")); flyweighrs.Add("C", new ConcreteFlyweight("C")); } public Flyweight GetFlyweight(string key) { return flyweighrs[key] as Flyweight; } }
/// <summary> /// 具体享元类,把共享的字母作为享元对象的内部状态 /// </summary> public class ConcreteFlyweight:Flyweight { /// <summary> /// 内蕴状态 /// </summary> private string intrinsicstate; /// <summary> /// 构造函数 /// </summary> /// <param name="innerState">内蕴状态</param> public ConcreteFlyweight(string innerState) { this.intrinsicstate = innerState; } /// <summary> /// 享元类的实例方法 /// </summary> /// <param name="extrinsicstate">外蕴状态</param> public override void Operation(int extrinsicstate) { Console.WriteLine("具体实现类:intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate); } }
/// <summary> /// C#设计模式-享元模式 /// </summary> class Program { static void Main(string[] args) { // 定义外部状态,例如字母的位置等信息 int externalstate = 10; FlyweightFactory factory = new FlyweightFactory(); Flyweight fa = factory.GetFlyweight("A"); if (fa != null) { fa.Operation(--externalstate); } // 判断是否已经创建了字母B Flyweight fb = factory.GetFlyweight("B"); if (fb != null) { fb.Operation(--externalstate); } // 判断是否已经创建了字母C Flyweight fc = factory.GetFlyweight("C"); if (fc != null) { fc.Operation(--externalstate); } // 判断是否已经创建了字母D Flyweight fd = factory.GetFlyweight("D"); if (fd != null) { fd.Operation(--externalstate); } else { Console.WriteLine("驻留池里面不存在字符串D"); ConcreteFlyweight d = new ConcreteFlyweight("D"); factory.flyweighrs.Add("D", d); d.Operation(--externalstate); } } }角色:
(1) 抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。
(2) 具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
(3) 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!
(4) 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
优缺点:
优点:降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
缺点:为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑更复杂,使系统复杂化。享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
使用场景:如果一个应用程序使用了大量的对象,而这些对象造如果发现某个对象的生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享大幅度单个实例的数目。