(一)享元模式概述
享元模式:从名字也可以看出享元,共享,这就是程序里面说的共享经济,官方说法就是:利用共享技术有效的支持大量细粒对象;简单的就是大对象共享吧,因为大对象创建耗时耗,耗资源。下面看一个最普通的例子,也是享元模式的经典应用,下面这个例子的输出的结果是什么?
string testStr = "zhangzhen"; string name = "zhangzhen"; Console.WriteLine(testStr==name); //比较值 Console.WriteLine(testStr.Equals(name));//比较值 Console.WriteLine(Object.ReferenceEquals(testStr,name));//比较引用
大家从结果中,也可以发现字符串的恒等性,其实就是利用了享元模式的创建,不然内存中字符串得占多少内存。下面且听我详细的介绍字符串的是如何实现恒等性。
一般对象都是按照上面这种创建方式,但是字符串呢,是不会这么干的,因为字符串这个对象在我们一个程序中,存在的实在太多了,所以语言的设计者们,就用了享元模式的思想。
如上图所示,就是这样做到字符串的恒等性,也就是我们一开始那三个答案都是为true; 继续我们的思考,程序设计语言者们是如何利用享元模式做到字符串的恒等性呢。
(二)享元模式的实现
继续上面所说的,然后带着我们应该怎么做呢,怎么做到共享呢,我们应该建立一个HashSet来存放已有的对象,每次对象的创建的时候,都去判断一下是否存在HashSet里面,我们应该把对象放到缓存,然后再判断,还是啥的,等等各种想法
带着上面的问题,我们来看接下来这个例子:
一般的享元工厂类(这里是一个简单工厂)
public class FlyweightFactory { //对象共享 private static Dictionary<WordType, BaseWord> _FlyweightFactoryDictionary = new Dictionary<WordType, BaseWord>(); private static readonly object FlyweightFactoryLock = new object(); public static BaseWord CreateWord(WordType wordType) { if (!_FlyweightFactoryDictionary.ContainsKey(wordType))//是在对象初始化之后,不再进去锁,保证多线程并发 { lock (FlyweightFactoryLock)//保证只有一个线程能进入,其他的排队 就是变成单线程 { if (!_FlyweightFactoryDictionary.ContainsKey(wordType))//如果不存在,则创建并写入字典 { BaseWord baseWord = null; switch (wordType) { case WordType.A: baseWord = new A(); break; case WordType.B: baseWord = new B(); break; case WordType.C: baseWord = new C(); break; default: throw new Exception("wrong wordType"); } _FlyweightFactoryDictionary[wordType] = baseWord; } } } return _FlyweightFactoryDictionary[wordType]; } public enum WordType { A, B, C, }
享元工厂主要是为了解决对象的重用问题(大对象),减少频繁的创建和销毁。但是它不是属于那种强制性的,它的思想值得我们学习,也行我们不一定非要为了享元而享元。