我们都知道,现实世界的东西都是通过用对象的形式来描述以此让它们存在于我们的软件世界里,所以,在软件世界中,现实世界的任何东西都能以对象的形式存在于软件世界中,大到宇宙星辰,小到砂砾尘埃,毫不客气的说,我们程序猿们如果想要个女朋友的话,直接创建一个女朋友类,然后new它一下就能轻松脱单了(咳咳),扯得太远了,让我们进入今天的正题,享元模式,所谓的享元,就是共享对象,那何为共享对象呢?我们在new一个对象的时候,电脑会在内存中开辟一个空间用来存储我们这个对象,今天,我们的享元模式,就是共享这个空间,好了,前提说完,我们先创建一个享元对象吧
abstract class Flyweight { public abstract void Operation(int extrinsicetate); }
很简单,Flyweight就是我们今天的享元对象的抽象,抽象类创建完成,按照国际惯例我们就要去实现它
class ConcreteFlyweight : Flyweight { public override void Operation(int extrinsicetate) { Console.WriteLine("具体Flyweight:" + extrinsicetate); } }
实现类也是超级简单,重写父类方法,然后在内部打印一句话,这里的extrinsicetate参数我们可以理解为编号,用来区分;到这里,享元类是创建完成了,如何做到享元呢,其实我们直接可以就new它,然后通过赋值的形式就可以实现享元了,但是我们的追求应该不止于此,我们要把享元类管理起来,我们可以设置在一个地方统一new对象和管理,这样当我们需要对象的时候直接拿就好了,这就是我们今天享元模式最关键的一个工厂类了,享元工厂
class FlyweightFactory { private Hashtable flyweights = new Hashtable(); private static FlyweightFactory factory = new FlyweightFactory(); private FlyweightFactory() { flyweights.Add("X", new ConcreteFlyweight()); flyweights.Add("Y", new ConcreteFlyweight()); flyweights.Add("Z", new ConcreteFlyweight()); } public static FlyweightFactory getFactory() { return factory; } public Flyweight GetFlyweight(string key) { if (flyweights.ContainsKey(key)) return ((Flyweight)flyweights[key]); else { flyweights.Add(key, new ConcreteFlyweight()); return ((Flyweight)flyweights[key]); } } }
FlyweightFactory就是我们的享元工厂,首先,我们创建了两个私有对象,一个是我们的享元工厂,另一个是我们用来存储享元对象的,这里我们用了单例模式来限制我们的享元工厂只能有一个,所有需要享元对象的都只能到我这里来拿,然后我们再看GetFlyweight方法,这个方法就是判断hashtable中有没有我们需要的享元对象,如果有就返回,没有就创建一个加入到hashtable中然后再返回,这里我们可以看到if和else中有一段相同的代码,那我们是不是应该把它给提炼出来呢,而且if和else的大括号看起来也不清爽,我们给它修剪修剪
public Flyweight GetFlyweight(string key) { if (!flyweights.ContainsKey(key)) flyweights.Add(key, new ConcreteFlyweight()); return ((Flyweight)flyweights[key]); }
好了,由原先的六行代码变成现在的一行代码,看起来也清爽了不少啊,而且逻辑也比较清晰:当hashtable中不存在请求的键时,我们就创建这个键的对象,然后返回对象,OK,完美,三个对象,就完成我们今天所要讲的享元模式了,接下来,让我们看看上端调用实现吧
class Program { static void Main(string[] args) { int extrinsicstate = 0; FlyweightFactory f = FlyweightFactory.getFactory(); Flyweight fx = f.GetFlyweight("X"); fx.Operation(++extrinsicstate); Flyweight fy = f.GetFlyweight("Y"); fy.Operation(++extrinsicstate); Flyweight fz = f.GetFlyweight("Z"); fz.Operation(++extrinsicstate); Console.Read(); } }
首先,我们通过getFactory方法获取享元工厂,然后再通过键来获取具体的享元类,这里注意的是我们创建了三个不同种类的享元类,分别是X、Y、Z,这三个类他们是不享元的,他们是三个不同的实例,也就是说他们不共享一个存储空间,我们今天所说的享元是这样
class Program { static void Main(string[] args) { int extrinsicstate = 0; FlyweightFactory f = FlyweightFactory.getFactory(); Flyweight fx = f.GetFlyweight("X"); fx.Operation(++extrinsicstate); Flyweight fy = f.GetFlyweight("X"); fy.Operation(++extrinsicstate); Flyweight fz = f.GetFlyweight("X"); fz.Operation(++extrinsicstate); Console.Read(); } }
这样我们获取到的才是同一个实例,这样fx、fy、fz三个对象才实现了享元,因为他们共用一个存储空间。好了,今天的享元模式就讲完了
享元模式:运用共享技术有效的支持大量细粒度对象的复用。系统只适用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。