(一)享元模式概述
享元模式:从名字也可以看出享元,共享,这就是程序里面说的共享经济,官方说法就是:利用共享技术有效的支持大量细粒对象;简单的就是大对象共享吧,因为大对象创建耗时耗,耗资源。下面看一个最普通的例子,也是享元模式的经典应用,下面这个例子的输出的结果是什么?
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,
}
享元工厂主要是为了解决对象的重用问题(大对象),减少频繁的创建和销毁。但是它不是属于那种强制性的,它的思想值得我们学习,也行我们不一定非要为了享元而享元。